etl : la chaîne passe aux dix minutes, l'agrégat continu suit (#246) #248

Merged
gabriel merged 2 commits from olivier/246-cadence-dix-minutes into develop 2026-09-09 14:01:50 +00:00
Member

Ferme #246.

Ce que ça change

La chaîne ETL passe du quart d'heure aux dix minutes, et l'agrégat continu suit dans le même lot. L'âge de la dernière minute dans public.mesure — ce que le pavé « état des sites » affiche — tombe de 28-87 minutes à 6-15, et le seau horaire devient lisible à (H+1):10.

argent or chargement politique mesure_horaire
avant, sur la machine :00 :17 :27 1 h / 1 h (0016)
avant, déclaré (#205) :00 :15 :30 :45 +3 +8 15 min / 15 min (0020)
ici :00 :10 :20 :30 :40 :50 +3 +5 10 min / 10 min (0022)

Les trois minutes derrière l'argent ne bougent pas. C'est la marge la plus serrée de la chaîne — la passe de 00:00, qui clôt la veille, écrit 1 440 minutes × 7 sites, soit ~1 min sur les 28 s mesurées pour une demi-journée — et la seule que le verrou de la zone or ne couvre pas. Les minutes ont donc été prises sur l'écart or → chargement, que le verrou couvre, ramené de cinq à deux.

Ce que ça ne fait pas, et il faut le lire avant d'approuver

Ce n'est pas du temps réel, et le mot n'apparaît nulle part dans le lot : c'est une chaîne par lots dont le lot fait dix minutes. Une minute est prise par la première passe argent strictement postérieure (la grille s'arrête aux minutes révolues), puis écrite par le chargement cinq minutes plus tard : d'où 6 au mieux, 15 au pire, 10 en moyenne. Un plafond ferme à dix minutes demanderait une cadence de cinq.

Et dix minutes est le plancher de la forme actuelle. La passe argent relit la journée entière à chaque tourcharger énumère les deux endpoints de bronze par site et par jour, elle ne traite pas l'incrément. Six passages par heure portent la lecture de bronze à ~6 min/h. Descendre à cinq minutes demande de la rendre incrémentale, et de le mesurer d'abord ; ça n'est pas fait ici et ne doit pas l'être en resserrant les minutes.

Trois erreurs trouvées en route

1. La cadence était écrite à un second endroit, et le rebasage ne pouvait pas le voir. Le #244 (fusionné pendant que j'écrivais ce lot) fait publier par chaque lanceur son intervalle de crontab via ops_publier_resultatev_ops_tache_cadence_secondes. Les trois de l'ETL déclaraient encore 900. Le rebasage est passé sans conflit : deux modifications du même fichier à des endroits différents. Le tableau de bord etl divise l'âge de la dernière réussite par cette valeur, et l'alerte du #228 se déclenche au-delà de trois fois — une valeur périmée ne casse rien de visible, elle desserre l'alerte en silence : 45 minutes de chaîne arrêtée tolérées au lieu de 30. Corrigé, et le banc contrôle désormais les sept tâches, crontab contre valeur déclarée.

2. La borne d'attente du verrou valait 900 s. Posée pour une chaîne horaire (« un quart de la cadence », dit son commentaire), jamais suivie au passage au quart d'heure : elle dépassait alors la cadence entière, soit exactement l'empilement de processus qu'elle empêche. Elle passe à 150 s.

3. Un commentaire de taches_planifiees était faux dans ses deux moitiés. Il affirmait que la passe de minuit « sort sans rien écrire, quatre fois par jour au quart d'heure ». Vérifié dans le code : _jour_demande la fait basculer sur la veille, qu'elle clôt — elle écrit 1 440 minutes, c'est la passe la plus lourde du jour. Le garde-fou visé n'est atteint que par un --jour explicite, et une seule passe par jour tombe à 00:00, quelle que soit la cadence.

Le banc ne code plus la cadence en dur

Le #205 avait écrit le quart d'heure à trois endroits de test-fraicheur-chaine.sh — nombre de passes, borne de politique en (minute / 15 + 1) * 15, et interval '15 minutes' attendu — qu'il fallait réécrire ensemble. Il nommait aussi 0020_fraicheur_zone_or.sql en dur : il serait resté vert sur une politique périmée, puisque chaque migration retire la précédente. Désormais il lit la cadence dans taches_planifiees, vérifie qu'elle est régulière (six passes groupées dans la première minute donnaient une cadence apparente de dix), prend la dernière migration qui pose une politique, et y confronte les deux réglages.

Contre-épreuves jouées : crontab seule ramenée au quart d'heure → rouge ; politique seule → rouge ; 0022 retirée, la 0020 redevient la dernière → rouge ; six passes dans la première minute → rouge.

Vérifications

Toutes jouées sur services/api/.venv (3.14, duckdb + psycopg présents) et avec l'outillage épinglé de requirements-ci.txt.

shellcheck …                       0 constat sur les fichiers du lot
ruff check / format                OK
mypy --strict etl                  24 fichiers, 0 erreur
pytest tests/unit -q               1101 passés, 1 ignoré
tests/ci/test-fraicheur-chaine.sh  19 contrôles verts
tests/ci/test-supervision.sh       vert
tests/ci/test-role-app.yml         failed=0
yamllint 1.38.0 / ansible-lint 26.8.0 (profil moderate)  0 constat
ansible-playbook --syntax-check    bootstrap, site, restore

Non vérifié : rien sur la machine. Le lot ne modifie que des déclarations — crontab, politique, documentation — et sa preuve réelle est le relevé d'après déploiement, écrit dans #246.

⚠️ La chaîne sortira rouge, et pas à cause de ce lot

shellcheck tests/ci/*.sh remonte SC2034 sur tests/ci/test-supervision.sh ligne 495, fichier du #244 que ce lot ne touche pas. Le constat est présent sur develop (vérifié sur origin/develop), donc develop est déjà rouge à cette étape.

C'est un faux positif : OPS_TEXTFILE_DIR est bien lu, par une fonction du fichier chargé dynamiquement (# shellcheck disable=SC1090), et les assertions du banc le prouvent en passant. Un # shellcheck disable=SC2034 suffit. Je ne l'ai pas fait ici : c'est le fichier du #244 et ça n'a rien à voir avec la cadence. À traiter dans un lot d'une ligne, chez son auteur.

Déploiement

L'ordre n'est pas indifférent : la crontab d'abord, la politique ensuite. Les deux voyagent dans le même lot et --tags app les pose ensemble ; la migration passe au démarrage de l'API. Le premier contrôle après déploiement verra encore l'ancien retard — la migration ne peut pas appeler refresh_continuous_aggregate (il refuse de tourner dans une transaction), le rattrapage a lieu au premier passage de la politique, dix minutes plus tard au pire.

Rappel : la machine a deux cadences de retard, le quart d'heure du #205 n'ayant jamais été déployé. C'est ce déploiement qui rendra les 1 h → 10 min visibles, pas la fusion.

Retour arrière en fin de 0022, et il se joue avec celui de taches_planifiees : les deux moitiés se défont ensemble, sans quoi le banc refuse le dépôt.

🤖 Generated with Claude Code

Ferme #246. ## Ce que ça change La chaîne ETL passe **du quart d'heure aux dix minutes**, et l'agrégat continu suit dans le même lot. L'âge de la dernière minute dans `public.mesure` — ce que le pavé « état des sites » affiche — tombe de **28-87 minutes à 6-15**, et le seau horaire devient lisible à `(H+1):10`. | | argent | or | chargement | politique `mesure_horaire` | |---|---|---|---|---| | avant, sur la machine | `:00` | `:17` | `:27` | 1 h / 1 h (0016) | | avant, déclaré (#205) | `:00 :15 :30 :45` | `+3` | `+8` | 15 min / 15 min (0020) | | **ici** | `:00 :10 :20 :30 :40 :50` | `+3` | `+5` | **10 min / 10 min (0022)** | **Les trois minutes derrière l'argent ne bougent pas.** C'est la marge la plus serrée de la chaîne — la passe de 00:00, qui clôt la veille, écrit 1 440 minutes × 7 sites, soit ~1 min sur les 28 s mesurées pour une demi-journée — et la **seule que le verrou de la zone or ne couvre pas**. Les minutes ont donc été prises sur l'écart or → chargement, que le verrou couvre, ramené de cinq à deux. ## Ce que ça ne fait pas, et il faut le lire avant d'approuver **Ce n'est pas du temps réel**, et le mot n'apparaît nulle part dans le lot : c'est une chaîne par lots dont le lot fait dix minutes. Une minute est prise par la première passe argent **strictement** postérieure (la grille s'arrête aux minutes révolues), puis écrite par le chargement cinq minutes plus tard : d'où 6 au mieux, 15 au pire, 10 en moyenne. Un plafond ferme à dix minutes demanderait une cadence de cinq. **Et dix minutes est le plancher de la forme actuelle.** La passe argent **relit la journée entière à chaque tour** — `charger` énumère les deux endpoints de bronze par site et par jour, elle ne traite pas l'incrément. Six passages par heure portent la lecture de bronze à ~6 min/h. Descendre à cinq minutes demande de la rendre incrémentale, et de le **mesurer** d'abord ; ça n'est pas fait ici et ne doit pas l'être en resserrant les minutes. ## Trois erreurs trouvées en route **1. La cadence était écrite à un second endroit, et le rebasage ne pouvait pas le voir.** Le #244 (fusionné pendant que j'écrivais ce lot) fait publier par chaque lanceur son intervalle de crontab via `ops_publier_resultat` → `ev_ops_tache_cadence_secondes`. Les trois de l'ETL déclaraient encore `900`. Le rebasage est passé **sans conflit** : deux modifications du même fichier à des endroits différents. Le tableau de bord `etl` divise l'âge de la dernière réussite par cette valeur, et l'alerte du #228 se déclenche au-delà de trois fois — une valeur périmée ne casse rien de visible, elle **desserre l'alerte en silence** : 45 minutes de chaîne arrêtée tolérées au lieu de 30. Corrigé, et le banc contrôle désormais les **sept** tâches, crontab contre valeur déclarée. **2. La borne d'attente du verrou valait 900 s.** Posée pour une chaîne horaire (« un quart de la cadence », dit son commentaire), jamais suivie au passage au quart d'heure : elle dépassait alors la cadence entière, soit exactement l'empilement de processus qu'elle empêche. Elle passe à 150 s. **3. Un commentaire de `taches_planifiees` était faux dans ses deux moitiés.** Il affirmait que la passe de minuit « sort sans rien écrire, quatre fois par jour au quart d'heure ». Vérifié dans le code : `_jour_demande` la fait basculer sur la veille, qu'elle clôt — elle écrit 1 440 minutes, c'est la passe **la plus lourde** du jour. Le garde-fou visé n'est atteint que par un `--jour` explicite, et une seule passe par jour tombe à 00:00, quelle que soit la cadence. ## Le banc ne code plus la cadence en dur Le #205 avait écrit le quart d'heure à **trois** endroits de `test-fraicheur-chaine.sh` — nombre de passes, borne de politique en `(minute / 15 + 1) * 15`, et `interval '15 minutes'` attendu — qu'il fallait réécrire ensemble. Il nommait aussi `0020_fraicheur_zone_or.sql` en dur : il serait resté **vert sur une politique périmée**, puisque chaque migration retire la précédente. Désormais il lit la cadence dans `taches_planifiees`, vérifie qu'elle est **régulière** (six passes groupées dans la première minute donnaient une cadence apparente de dix), prend la **dernière** migration qui pose une politique, et y confronte les deux réglages. Contre-épreuves jouées : crontab seule ramenée au quart d'heure → rouge ; politique seule → rouge ; `0022` retirée, la `0020` redevient la dernière → rouge ; six passes dans la première minute → rouge. ## Vérifications Toutes jouées sur `services/api/.venv` (3.14, `duckdb` + `psycopg` présents) et avec l'outillage épinglé de `requirements-ci.txt`. ``` shellcheck … 0 constat sur les fichiers du lot ruff check / format OK mypy --strict etl 24 fichiers, 0 erreur pytest tests/unit -q 1101 passés, 1 ignoré tests/ci/test-fraicheur-chaine.sh 19 contrôles verts tests/ci/test-supervision.sh vert tests/ci/test-role-app.yml failed=0 yamllint 1.38.0 / ansible-lint 26.8.0 (profil moderate) 0 constat ansible-playbook --syntax-check bootstrap, site, restore ``` **Non vérifié :** rien sur la machine. Le lot ne modifie que des déclarations — crontab, politique, documentation — et sa preuve réelle est le relevé d'après déploiement, écrit dans #246. ## ⚠️ La chaîne sortira rouge, et pas à cause de ce lot `shellcheck tests/ci/*.sh` remonte **SC2034 sur `tests/ci/test-supervision.sh` ligne 495**, fichier du #244 que ce lot ne touche pas. Le constat est présent **sur `develop`** (vérifié sur `origin/develop`), donc `develop` est déjà rouge à cette étape. C'est un **faux positif** : `OPS_TEXTFILE_DIR` est bien lu, par une fonction du fichier chargé dynamiquement (`# shellcheck disable=SC1090`), et les assertions du banc le prouvent en passant. Un `# shellcheck disable=SC2034` suffit. Je ne l'ai pas fait ici : c'est le fichier du #244 et ça n'a rien à voir avec la cadence. À traiter dans un lot d'une ligne, chez son auteur. ## Déploiement **L'ordre n'est pas indifférent : la crontab d'abord, la politique ensuite.** Les deux voyagent dans le même lot et `--tags app` les pose ensemble ; la migration passe au démarrage de l'API. Le premier contrôle après déploiement verra **encore l'ancien retard** — la migration ne peut pas appeler `refresh_continuous_aggregate` (il refuse de tourner dans une transaction), le rattrapage a lieu au premier passage de la politique, dix minutes plus tard au pire. Rappel : la machine a **deux cadences de retard**, le quart d'heure du #205 n'ayant jamais été déployé. C'est ce déploiement qui rendra les 1 h → 10 min visibles, pas la fusion. Retour arrière en fin de `0022`, et il se joue **avec** celui de `taches_planifiees` : les deux moitiés se défont ensemble, sans quoi le banc refuse le dépôt. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
etl: la chaine passe aux dix minutes, l agregat continu suit (#246)
Some checks failed
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 47s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 8s
Intégration / Terraform — format, validité et lint (pull_request) Successful in 23s
Intégration / Checkov — audit de la configuration (pull_request) Failing after 41s
Intégration / Workflows — lint et audit de sécurité (pull_request) Failing after 17s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m42s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 5m43s
fb5a5b11a6
La serie au pas de la minute que le pave « etat des sites » affiche a
entre 28 et 87 minutes d age sur la machine : la crontab de `deploy`
porte encore la chaine horaire, et le chargement n ecrit les minutes de
l heure H qu a (H+1):27. Le #205 a ramene la chaine au quart d heure
pour la PREVISION, qui lit `mesure_horaire` ; il ne visait pas la serie,
que `dashboard/repository.py` lit dans `public.mesure`.

Les trois passes passent aux dix minutes — :00 :10 …, l or trois
minutes derriere, le chargement deux de plus — et la migration 0022
ramene `end_offset` et `schedule_interval` de `mesure_horaire` aux dix
minutes avec elles. L age de la derniere minute en base tombe de 28-87
a 6-15 minutes, et le seau horaire devient lisible a (H+1):10.

LES TROIS MINUTES DERRIERE L ARGENT NE BOUGENT PAS. C est la marge la
plus serree de la chaine — trois fois la duree d une passe de fin de
journee — et la seule que le verrou de la zone or ne couvre pas. Les
minutes gagnees ont donc ete prises sur l ecart or → chargement, que le
verrou couvre, ramene de cinq a deux.

Le banc de fraicheur ne code plus la cadence en dur : il la LIT dans
`taches_planifiees`, verifie qu elle est reguliere, et y confronte la
politique de la derniere migration qui en pose une. Le #205 avait ecrit
le quart d heure a trois endroits du banc, qu il fallait reecrire
ensemble ; une troisieme cadence n aura plus a y toucher. Le banc
nommait aussi `0020_fraicheur_zone_or.sql` en dur : il serait reste vert
sur une politique perimee.

TROIS ERREURS CORRIGEES AU PASSAGE.

La cadence etait ecrite a un SECOND endroit, et le rebasage sur le #244
ne pouvait pas le voir : les trois lanceurs passent leur intervalle a
`ops_publier_resultat`, qui publie `ev_ops_tache_cadence_secondes`, et
ils declaraient encore 900 s. Le tableau de bord `etl` divise l age de
la derniere reussite par cette valeur et l alerte du #228 se declenche
au dela de trois fois : une valeur perimee ne casse rien de visible,
elle DESSERRE l alerte en silence — 45 minutes de chaine arretee
tolerees au lieu de 30. Le banc controle desormais les SEPT taches,
crontab contre valeur declaree.

La borne d attente du verrou valait 900 s, posee pour une chaine horaire
et jamais suivie au quart d heure — elle depassait la cadence entiere,
soit exactement l empilement de processus qu elle empeche. Elle passe a
150 s, le quart de la cadence que son commentaire annonce.

Le commentaire de `taches_planifiees` affirmait que la passe de minuit
« sort sans rien ecrire, quatre fois par jour au quart d heure ».
Verifie dans `silver/job.py` et `silver/grille.py` : `_jour_demande` la
fait basculer sur la veille, qu elle clot, donc elle ecrit 1 440 minutes
et c est la passe la plus lourde du jour. Le garde-fou vise n est
atteint que par un `--jour` explicite, et une seule passe par jour tombe
a 00:00 quelle que soit la cadence.

Ce n est pas du temps reel, et le mot n est pas employe : c est une
chaine par lots dont le lot fait dix minutes. Dix minutes est le
plancher de cette forme — la passe argent relit la journee entiere a
chaque tour. Descendre a cinq demande de la rendre incrementale, et de
le mesurer d abord.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
Member

Verdict de la chaîne sur fb5a5b11

Job Verdict
Python — qualité, tests et dépendances
Tableau de bord — dépendances, tests et construction
Contrôles statiques du dépôt
Terraform — format, validité et lint
Infra Ansible — Playbooks Ansible valides
Checkov — audit de la configuration
Workflows — lint et audit de sécurité

Les deux rouges sont ceux de develop, et ce lot n'en ajoute aucun. Vérifié sur le commit b5667d6 de develop, en push, avant que cette branche existe : le même couple échoue, exactement. L'ensemble des échecs est donc identique, et cette PR ajoute en plus un job que develop ne joue pas — « Infra Ansible », filtré par chemin — qui est vert.

  • Checkov : le scan a été ajouté par le #72 (PR #242), fusionné juste avant ce lot, et il échoue sur la configuration Terraform existante. Ce lot ne contient aucun fichier .tf, docker-compose ni Dockerfile.
  • Workflows : shellcheck remonte SC2034 sur tests/ci/test-supervision.sh:495, fichier du #244 (PR #245) que ce lot ne touche pas. C'est un faux positifOPS_TEXTFILE_DIR est bien lu, par une fonction du fichier chargé dynamiquement (# shellcheck disable=SC1090), et les assertions du banc le prouvent en passant. Un # shellcheck disable=SC2034 suffit.

⚠️ Et ce rouge en cache deux contrôles non joués. Dans ce job, les étapes sont séquentielles sous sh -e : l'échec de shellcheck laisse yamllint et zizmor à l'état « ignoré ». Ne pas lire ce job comme « seul shellcheck a un reproche ». Les deux ont été joués localement sur ce lot, à l'outillage épinglé de requirements-ci.txt :

yamllint 1.38.0      infra/ansible        0 constat
ansible-lint 26.8.0  profil moderate      0 constat (le profil « production » passe aussi)

Aucun des deux échecs n'appartient à ce ticket, et je ne les ai pas corrigés ici — mêler un correctif de chaîne à un changement de cadence rendrait la relecture moins claire, et le second appartient à l'auteur du #244. Ils bloquent en revanche la fusion de toute PR : ils méritent leur propre ticket.

🤖 Generated with Claude Code

## Verdict de la chaîne sur `fb5a5b11` | Job | Verdict | |---|---| | Python — qualité, tests et dépendances | ✅ | | Tableau de bord — dépendances, tests et construction | ✅ | | Contrôles statiques du dépôt | ✅ | | Terraform — format, validité et lint | ✅ | | **Infra Ansible — Playbooks Ansible valides** | ✅ | | Checkov — audit de la configuration | ❌ | | Workflows — lint et audit de sécurité | ❌ | **Les deux rouges sont ceux de `develop`, et ce lot n'en ajoute aucun.** Vérifié sur le commit `b5667d6` de `develop`, en `push`, avant que cette branche existe : le même couple échoue, exactement. L'ensemble des échecs est donc **identique**, et cette PR ajoute en plus un job que `develop` ne joue pas — « Infra Ansible », filtré par chemin — qui est **vert**. - **Checkov** : le scan a été ajouté par le #72 (PR #242), fusionné juste avant ce lot, et il échoue sur la configuration Terraform existante. Ce lot ne contient aucun fichier `.tf`, `docker-compose` ni `Dockerfile`. - **Workflows** : `shellcheck` remonte **SC2034 sur `tests/ci/test-supervision.sh:495`**, fichier du #244 (PR #245) que ce lot ne touche pas. C'est un **faux positif** — `OPS_TEXTFILE_DIR` est bien lu, par une fonction du fichier chargé dynamiquement (`# shellcheck disable=SC1090`), et les assertions du banc le prouvent en passant. Un `# shellcheck disable=SC2034` suffit. ⚠️ **Et ce rouge en cache deux contrôles non joués.** Dans ce job, les étapes sont séquentielles sous `sh -e` : l'échec de `shellcheck` laisse **yamllint et zizmor à l'état « ignoré »**. Ne pas lire ce job comme « seul shellcheck a un reproche ». Les deux ont été joués localement sur ce lot, à l'outillage épinglé de `requirements-ci.txt` : ``` yamllint 1.38.0 infra/ansible 0 constat ansible-lint 26.8.0 profil moderate 0 constat (le profil « production » passe aussi) ``` Aucun des deux échecs n'appartient à ce ticket, et je ne les ai pas corrigés ici — mêler un correctif de chaîne à un changement de cadence rendrait la relecture moins claire, et le second appartient à l'auteur du #244. Ils bloquent en revanche la fusion de **toute** PR : ils méritent leur propre ticket. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ci: shellcheck rougit sur un faux positif, et il masque deux etapes (#246)
Some checks failed
Intégration / Tableau de bord — dépendances, tests et construction (pull_request) Successful in 48s
Intégration / Contrôles statiques du dépôt (pull_request) Successful in 8s
Intégration / Terraform — format, validité et lint (pull_request) Successful in 24s
Intégration / Checkov — audit de la configuration (pull_request) Failing after 42s
Intégration / Workflows — lint et audit de sécurité (pull_request) Successful in 17s
Infra Ansible / Playbooks Ansible valides (pull_request) Successful in 1m22s
Intégration / Python — qualité, tests et dépendances (pull_request) Successful in 5m48s
4c08c290cb
`shellcheck tests/ci/*.sh` remonte SC2034 sur test-supervision.sh:495,
« OPS_TEXTFILE_DIR appears unused ». La variable est en fait lue par
`ops_ecrire`, dans bin/_metriques-ops.sh charge juste au-dessus (lignes
52-53 et 65-66) ; shellcheck ne peut pas le voir puisque la source est
dynamique, d ou le SC1090 deja pose sur la ligne precedente. Le controle
qui suit le prouve : sans cette affectation, `ev_etl_argent.prom` ne
serait pas ecrit dans le bac et l assertion echouerait.

CE N EST PAS UN ROUGE ISOLE, ET C EST LA VRAIE RAISON DE CE COMMIT. Dans
le job « Workflows », les etapes sont sequentielles sous `sh -e` :
l echec de shellcheck laissait yamllint ET zizmor a l etat « ignoree ».
Deux audits ne tournaient plus, et le rapport ne le disait pas en ces
termes — on lisait « seul shellcheck a un reproche ». Les deux sont
joues ici, a l outillage epingle de .forgejo/requirements-meta.txt
(yamllint 1.38.0, zizmor 1.30.0), avec les memes arguments que la
chaine : code 0 tous les deux, « No findings to report » pour zizmor.

Une directive plutot qu un `export` : la fonction tourne dans CE shell,
elle n a pas besoin de l environnement, et exporter donnerait a croire
qu un sous-processus la lit.

Le constat vient du #244 (PR #245) et il est present sur `develop` : ce
n est pas ce lot qui l a introduit, mais il bloque la fusion de toute
demande, dont celle-ci.

Le second rouge de `develop`, « Checkov », n est PAS traite ici : ce ne
sont pas des faux positifs mais huit constats de securite reels sur
`azurerm_storage_account.archive`, qui demandent un arbitrage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
Member

Verdict sur 4c08c290 — un des deux rouges est levé

Job fb5a5b1 4c08c290
Python — qualité, tests et dépendances
Tableau de bord
Contrôles statiques du dépôt
Terraform — format, validité et lint
Infra Ansible — Playbooks valides
Workflows — lint et audit de sécurité
Checkov — audit de la configuration #249

Ce que le correctif shellcheck a débloqué, au-delà de son propre rouge. Dans ce job les étapes sont séquentielles sous sh -e : l'échec de shellcheck laissait yamillint et zizmor à l'état « ignoré ». Deux audits ne tournaient plus, et le rapport ne le disait pas en ces termes. Ils tournent de nouveau, et ils passent — ce vert n'est donc pas « shellcheck corrigé », c'est « les trois étapes jouées ». Les deux avaient été rejoués en local avant la poussée, à l'outillage épinglé de .forgejo/requirements-meta.txt (yamllint 1.38.0, zizmor 1.30.0), avec les arguments exacts de la chaîne : code 0 des deux côtés, No findings to report pour zizmor.

Checkov n'est pas traité ici, et c'est une décision, pas un oubli

Rejoué en local avec le checkov épinglé (3.3.16) : 8 constats, tous sur azurerm_storage_account.archive. Six sont inapplicables et le dépôt écrit déjà pourquoi. Deux sont de vrais manques — suppression réversible (CKV2_AZURE_38) et politique d'expiration des SAS (CKV2_AZURE_41).

Deux règles écrites du dépôt interdisent de les traiter dans cette demande :

  • docs/runbooks/stockage-secours.md, § « Activer la suppression réversible » : « c'est une décision à prendre, pas un oubli. […] À ouvrir en ticket plutôt qu'à glisser dans une demande de fusion qui parle d'autre chose. »
  • l'en-tête de infra/terraform/.checkov.yml, en capitales : « CE QUI N'EST PAS UNE EXCEPTION ACCEPTABLE : ça fait rougir la chaîne. »

Rendre Checkov vert ici demandait donc soit d'enfreindre la première, soit d'exempter deux manques que stockage.tf signale lui-même comme « une décision à prendre ». D'où #249, qui porte les huit constats, l'argument vérifiable de chacun des six, et la mesure préparatoire : les deux correctifs Terraform essayés en local font passer 8 → 6, les six restants étant exactement les inapplicables.

Ce lot ne touche aucun fichier de infra/terraform/ — ni .tf, ni .checkov.yml.

Ce rouge est celui de develop : cette demande n'ajoute aucun échec, et elle en retire un.

🤖 Generated with Claude Code

## Verdict sur `4c08c290` — un des deux rouges est levé | Job | `fb5a5b1` | `4c08c290` | |---|---|---| | Python — qualité, tests et dépendances | ✅ | ✅ | | Tableau de bord | ✅ | ✅ | | Contrôles statiques du dépôt | ✅ | ✅ | | Terraform — format, validité et lint | ✅ | ✅ | | Infra Ansible — Playbooks valides | ✅ | ✅ | | **Workflows — lint et audit de sécurité** | ❌ | **✅** | | Checkov — audit de la configuration | ❌ | ❌ → #249 | **Ce que le correctif shellcheck a débloqué, au-delà de son propre rouge.** Dans ce job les étapes sont séquentielles sous `sh -e` : l'échec de `shellcheck` laissait **yamillint et zizmor à l'état « ignoré »**. Deux audits ne tournaient plus, et le rapport ne le disait pas en ces termes. Ils tournent de nouveau, et ils passent — ce vert n'est donc pas « shellcheck corrigé », c'est « les trois étapes jouées ». Les deux avaient été rejoués en local avant la poussée, à l'outillage épinglé de `.forgejo/requirements-meta.txt` (`yamllint 1.38.0`, `zizmor 1.30.0`), avec les arguments exacts de la chaîne : code 0 des deux côtés, `No findings to report` pour zizmor. ## Checkov n'est pas traité ici, et c'est une décision, pas un oubli Rejoué en local avec le checkov épinglé (`3.3.16`) : **8 constats, tous sur `azurerm_storage_account.archive`**. Six sont inapplicables et le dépôt écrit déjà pourquoi. **Deux sont de vrais manques** — suppression réversible (`CKV2_AZURE_38`) et politique d'expiration des SAS (`CKV2_AZURE_41`). Deux règles écrites du dépôt interdisent de les traiter dans cette demande : - `docs/runbooks/stockage-secours.md`, § « Activer la suppression réversible » : « c'est une décision à prendre, pas un oubli. […] **À ouvrir en ticket plutôt qu'à glisser dans une demande de fusion qui parle d'autre chose.** » - l'en-tête de `infra/terraform/.checkov.yml`, en capitales : « CE QUI N'EST PAS UNE EXCEPTION ACCEPTABLE : *ça fait rougir la chaîne*. » Rendre Checkov vert ici demandait donc soit d'enfreindre la première, soit d'exempter deux manques que `stockage.tf` signale lui-même comme « une décision à prendre ». D'où **#249**, qui porte les huit constats, l'argument vérifiable de chacun des six, et la mesure préparatoire : les deux correctifs Terraform essayés en local font passer 8 → 6, les six restants étant exactement les inapplicables. **Ce lot ne touche aucun fichier de `infra/terraform/`** — ni `.tf`, ni `.checkov.yml`. Ce rouge est celui de `develop` : cette demande n'ajoute aucun échec, et elle en retire un. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
gabriel approved these changes 2026-09-09 14:01:44 +00:00
gabriel merged commit 6ba6a5db7b into develop 2026-09-09 14:01:50 +00:00
gabriel deleted branch olivier/246-cadence-dix-minutes 2026-09-09 14:01:50 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
g2/enervision!248
No description provided.