Veille Firebird
généré 2026-09-05 17:09 UTC · dépôt · revue · propositions · catalogueCe matin 2026-09-05
| contrôle | valeur | seuil / base | 30 nuits | si rouge | |
|---|---|---|---|---|---|
| 🟥 | deps.auditVulnérabilités des dépendances 12 preuve(s)
| 65 high + critical (3 paquets) | rouge si value > 0 | Ouvrir l'avis, mettre à jour ou écrire l'exception (raison + date) — jamais ignorer sans note. Rouge attendu la première nuit : le stock est un chantier, pas un incident. | |
| 🟥 | deps.eolComposants de la pile en fin de vie 4 preuve(s)
| 4 composants en fin de vie | rouge si value > 0 | Ce n'est pas un correctif, c'est un chantier : le planifier (PLAN.md), avec une date. Rouge attendu dès la première nuit (Node 18, Next 12/13, MySQL 8.0). | |
| 🟥 | docs.lockfilesUn lockfile par paquet 1 preuve(s)
| 1 paquets sans lockfile unique | rouge si value > 0 | Supprimer le lockfile orphelin (api/yarn.lock — dette connue, CLAUDE.md « Tooling drift »). | |
| 🟥 | judge.reviewLa revue hebdomadaire 1 preuve(s)
| 999 jours depuis la dernière revue | rouge si value > 8 | Revue absente : lire le run « Revue hebdomadaire » (clé API ? périmètre refusé ?). Note basse : lire reviews/<semaine>.md — la preuve citée dit quel fichier. | |
| 🟥 | server.resourcesRessources du serveur 1 preuve(s)
| 77.8 % de disque libre | rouge si value < 15 || d.swap_total_gb === 0 | Sans swap, un `next build` peut être tué par le kernel (OOM du 2026-08-26, BACKLOG) : ajouter 2 Go de swap. Disque bas : purger les logs PM2 et les vieux builds. | |
| 🟧 | docs.migrations_rootMigrations en attente 2 preuve(s)
| 2 migrations en attente | orange si value > 0 | Déployer (elle est dûe) ou archiver dans applied/ (elle l'est déjà) — `node scripts/migrate.mjs status` tranche. | |
| ⬜ | db.slow_queriesRequêtes lentes | slow_query_log est OFF sur le serveur — à activer (seuil 1 s) pour mesurer | — | ||
| 🟩 | ci.preprod_greenCI verte sur la tête de preprod | 0 workflows non verts sur la tête preprod | rouge si value > 0 | ||
| 🟩 | code.bigfilesFichiers de plus de 500 lignes 10 preuve(s)
| 39 fichiers > 500 lignes | ≤ 39 (base, tolérance 0 %) | ||
| 🟩 | code.cyclesCycles d'imports 12 preuve(s)
| 87 cycles d'imports (3 paquets) | ≤ 87 (base, tolérance 0 %) | ||
| 🟩 | code.deadCode mort 26 preuve(s)
| 429 fichiers + exports + types inutilisés (3 paquets) | ≤ 429 (base, tolérance 5 %) | ||
| 🟩 | code.dupCode dupliqué 10 preuve(s)
| 10.92 % de tokens dupliqués | ≤ 10.92 (base, tolérance 3 %) | ||
| 🟩 | code.strictness.apiDistance au mode strict (api) 8 preuve(s)
| 190 erreurs tsc --strict (api) | ≤ 190 (base, tolérance 2 %) | ||
| 🟩 | code.testsNombre de tests | 373 tests (E2E + API) | ≥ 373 (base, tolérance 0 %) | ||
| 🟩 | code.tooling_ratioPoids de l'outillage | 0.215 outillage ÷ produit (lignes) | ≤ 0.215 (base, tolérance 5 %) | ||
| 🟩 | db.dup_indexesIndex dupliqués | 0 index en double | rouge si value > 0 | ||
| 🟩 | db.fk_without_indexClés étrangères sans index | 0 FK sans index | ≤ 0 (base, tolérance 0 %) | ||
| 🟩 | db.migrationsÉtat des migrations sur la base vivante | 0 migrations en attente ou en alarme | rouge si d.alarms > 0 | ||
| 🟩 | db.sizesTaille de la base et croissance 8 preuve(s)
| 11.8 Mo (données + index) | rouge si d.growth_7d_pct > 50 | ||
| 🟩 | deploy.alignmentLe servi est le poussé | 0 écarts entre le servi et le poussé | rouge si d.stale_builds.length > 0 | ||
| 🟩 | deps.outdatedDépendances en retard d'une majeure 15 preuve(s)
| 106 dépendances ≥ 1 majeure de retard (3 paquets) | ≤ 106 (base, tolérance 5 %) | ||
| 🟩 | docs.email_registryRegistre des e-mails à jour | 0 écarts code ↔ registre des e-mails | rouge si value > 0 | ||
| 🟩 | docs.revision_collisionsNuméros de révision en double 7 preuve(s)
| 19 numéros de révision en double | ≤ 19 (base, tolérance 0 %) | ||
| 🟩 | errors.sentryErreurs nouvelles dans Sentry | 0 issues nouvelles en 24 h | rouge si d.regressed > 0 || value > 5 | 1 point | |
| 🟩 | http.latencyLatence p95 des routes de la sonde | 126 ms (p95 sur les routes de la sonde) | ≤ 167 (base, tolérance 30 % ou 150) | ||
| 🟩 | http.liveLes trois fronts répondent | 0 fronts en défaut (vie ou certificat) | rouge si value > 0 | ||
| 🟩 | http.productLa sonde produit passe | 0 routes en échec sur 8 | rouge si value > 0 | ||
| 🟩 | ops.backup_freshSauvegarde fraîche 2 preuve(s)
| 14.7 heures depuis le dernier backup OK | rouge si value > 26 || d.size_mb < 1 | ||
| 🟩 | ops.probes_stateLes sondes du serveur tournent | 0 sondes serveur en défaut | rouge si value > 0 | ||
| 🟩 | ops.restore_drillTest de restauration récent 1 preuve(s)
| 4.6 jours depuis le dernier restore-test OK | rouge si value > 35 | ||
| 🟩 | server.certbotRenouvellement TLS armé | 0 timer certbot inactif | rouge si value > 0 | ||
| 🟩 | server.pm2Process PM2 | 0 process attendus non « online » | rouge si value > 0 |
Revue hebdomadaire
Pas encore de revue. La première tourne le dimanche suivant la mise en place du lot 3.
Propositions et idées
À valider (toutes)
Aucune proposition ouverte.
Idées (+ nouvelle)
Aucune idée en attente.
Catalogue 34 / 40 contrôles · ≈ 19 / 25 min
| id | question | fréquence | seuil | coût | si rouge |
|---|---|---|---|---|---|
deps.audit | Une dépendance d'un des trois paquets porte-t-elle une CVE high ou critical connue ? | daily | rouge si value > 0 | 90 s | Ouvrir l'avis, mettre à jour ou écrire l'exception (raison + date) — jamais ignorer sans note. Rouge attendu la première nuit : le stock est un chantier, pas un incident. |
deps.outdated | Combien de dépendances ont au moins une version majeure de retard ? | daily | cliquet (lower) | 90 s | Une majeure de plus est apparue : la noter au chantier de mise à niveau, pas la subir. |
deps.eol | Node, Next ou MySQL tels que déployés sont-ils sortis du support de leur éditeur ? | daily | rouge si value > 0 | 5 s | Ce n'est pas un correctif, c'est un chantier : le planifier (PLAN.md), avec une date. Rouge attendu dès la première nuit (Node 18, Next 12/13, MySQL 8.0). |
code.dead | Combien de fichiers, exports et types ne sont importés par rien ? | daily | cliquet (lower) | 180 s | Supprimer ce qui vient d'être laissé mort, ou l'exporter pour une raison écrite (l'arbre app/src/redux/ orphelin est connu — CLAUDE.md). |
code.dup | Quelle part du code des trois sources est un copier-coller d'au moins 50 tokens ? | daily | cliquet (lower) | 60 s | Le clone le plus long de la liste de preuves est le premier à factoriser. Un agent qui réécrit au lieu de réutiliser laisse exactement cette trace. |
code.cycles | Combien de cycles d'imports les trois paquets portent-ils ? | daily | cliquet (lower) | 120 s | Un cycle de plus : l'extraire dans un module tiers (précédent : improve-agent ↔ evaluation-agent, BACKLOG). |
code.bigfiles | Combien de fichiers source dépassent 500 lignes ? | daily | cliquet (lower) | 10 s | Le fichier qui vient de franchir la barre se découpe maintenant, pas dans six mois. |
code.strictness.api | Combien d'erreurs `tsc --strict` l'API porterait-elle aujourd'hui ? | daily | cliquet (lower) | 120 s | Le code neuf ajoute de la dette strict : le corriger dans le commit qui l'a créée (la cible est strict, CLAUDE.md). |
code.tooling_ratio | L'outillage (scripts/, .claude/) grossit-il plus vite que le produit qu'il sert ? | daily | cliquet (lower) | 10 s | Avant d'ajouter un script, en retirer un. Le ratio initial (≈ 0,23) est la référence, pas un objectif. |
code.tests | Le nombre de tests (E2E + API) monte-t-il, ou quelqu'un en a-t-il retiré ? | daily | cliquet (higher) | 5 s | Un test a disparu : retrouver le commit et l'autorité de spec qui le justifie (barre A3 du dev loop). |
ci.preprod_green | Le dernier commit de `preprod` a-t-il tous ses checks verts ? | daily | rouge si value > 0 | 5 s | Lire le run rouge avant tout autre travail — 16 CI rouges d'affilée sont passées inaperçues un jour (cockpit, bannière CI). |
docs.migrations_root | Des migrations attendent-elles à la racine d'api/migrations/, et depuis combien de temps ? | daily | rouge si d.oldest_days > 7 | 2 s | Déployer (elle est dûe) ou archiver dans applied/ (elle l'est déjà) — `node scripts/migrate.mjs status` tranche. |
docs.email_registry | Le nombre de sites d'envoi dans le code correspond-il encore au registre docs/emails/REGISTRE.md ? | daily | rouge si value > 0 | 2 s | Un envoi est apparu ou a disparu sans passer par le registre : l'y inscrire (règle 11 CLAUDE.md), puis mettre à jour les valeurs attendues ici. |
docs.lockfiles | Chaque paquet a-t-il exactement un lockfile ? | daily | rouge si value > 0 | 1 s | Supprimer le lockfile orphelin (api/yarn.lock — dette connue, CLAUDE.md « Tooling drift »). |
docs.revision_collisions | Deux lignes de révision portent-elles le même numéro dans un même document ? | daily | cliquet (lower) | 1 s | Renuméroter la collision neuve dans le commit qui l'a créée ; le stock (19 au 2026-09-05) est un item BACKLOG. |
http.live | api, app et admin preprod répondent-ils en TLS valide, avec un certificat qui a plus de 14 jours devant lui ? | daily | rouge si value > 0 | 20 s | Incident : lire les logs PM2 du front concerné ; un certificat court = certbot.timer (server.certbot). |
http.product | Un admin dédié peut-il se connecter, imiter le persona et lire ses huit routes avec un corps sensé ? | daily | rouge si value > 0 | 60 s | Incident produit : la route en échec et sa raison sont dans les preuves ; c'est ce que verify-live-cron aurait dû mailer. |
http.latency | Les routes GET authentifiées de la sonde ralentissent-elles ? | daily | cliquet (lower) | 5 s | Profiler la route la plus lente (details.slowest) : EXPLAIN sur sa requête, puis index ou pagination. |
errors.sentry | Combien d'issues Sentry sont apparues en 24 h sur les trois projets, et y a-t-il des régressions ? | daily | rouge si d.regressed > 0 || value > 5 | 10 s | Trier : une régression est un bug réintroduit — retrouver le commit ; une nouvelle issue est lue avant d'être fermée. |
deploy.alignment | Le serveur preprod sert-il la tête de `preprod`, avec un front rebâti après le dernier pull ? | daily | rouge si d.stale_builds.length > 0 | 5 s | Un front plus vieux que le commit servi = déploiement mort à mi-chemin (OOM du 2026-08-26) : relancer deploy-preprod.sh. Un simple retard = déployer depuis /sessions. |
db.migrations | Que dit `migrate.mjs status firebird_preprod` : migrations en attente, et surtout alarmes (divergent, undeclared, drifted) ? | daily | rouge si d.alarms > 0 | 5 s | Une alarme est un désaccord entre le registre et la base : instruire avec api/migrations/README.md, jamais arbitrer en silence. |
db.dup_indexes | Des index portant exactement les mêmes colonnes coexistent-ils sur une table (le leak de sync alter) ? | daily | rouge si value > 0 | 5 s | Le leak est revenu (un `unique: true` de colonne réintroduit ?) — trouver le modèle, puis nettoyer à la main (cleanup-duplicate-indexes.sh est dev-only). |
db.fk_without_index | Une clé étrangère existe-t-elle sans index porteur ? | daily | cliquet (lower) | 5 s | Migration compagnon pour l'index (les deux moitiés : modèle + migration, CLAUDE.md). |
db.sizes | La base grossit-elle à un rythme normal (moins de 20 % par semaine) ? | daily | rouge si d.growth_7d_pct > 50 | 5 s | Regarder la table qui grossit (preuves) : une table de log sans purge, ou un seed rejoué en boucle. |
db.slow_queries | Combien de requêtes ont dépassé le seuil lent depuis la mesure précédente ? | daily | rouge si d.delta_24h > 50 | 5 s | Lire le slow log du serveur, EXPLAIN sur la requête, puis index ou pagination. |
server.resources | Le VPS a-t-il du disque, de la mémoire et un swap, sans charge anormale ? | daily | rouge si value < 15 || d.swap_total_gb === 0 | 5 s | Sans swap, un `next build` peut être tué par le kernel (OOM du 2026-08-26, BACKLOG) : ajouter 2 Go de swap. Disque bas : purger les logs PM2 et les vieux builds. |
server.pm2 | Les six process (preprod et prod) sont-ils online, et lesquels ont redémarré depuis 24 h ? | daily | rouge si value > 0 | 5 s | Un process absent ou errored : `pm2 logs <nom>` sur le serveur avant tout redémarrage — un EPERM ou un ENOENT dit une panne d'environnement, pas une régression. |
server.certbot | Le timer certbot est-il actif ? | daily | rouge si value > 0 | 2 s | `systemctl enable --now certbot.timer` (sudo) — le trou est noté DEPLOY.md §8. |
ops.backup_fresh | Le dernier backup B2 de preprod a-t-il moins de 26 h et une taille plausible ? | daily | rouge si value > 26 || d.size_mb < 1 | 2 s | Incident sauvegarde : lire backup.log sur le serveur (FATAL sur stderr), vérifier rclone (`rclone ls b2:Firebird-backups/daily/`), relancer à la main. |
ops.restore_drill | Le dernier test de restauration réussi date-t-il de moins de 35 jours ? | daily | rouge si value > 35 | 2 s | Rejouer à la main : `bash scripts/restore-test.sh firebird_preprod` sur le serveur (docs/runbooks/RESTORE.md), et lire pourquoi le cron du 1er n'a pas écrit OK. |
ops.probes_state | uptime-check et verify-live tournent-elles encore, et disent-elles « up » ? | daily | rouge si value > 0 | 2 s | Un fichier d'état figé = cron mort (crontab -l) ; un « down » ou « broken » = ce que le cron aurait dû mailer — vérifier msmtp. |
sec.headers | Les trois fronts preprod servent-ils HSTS, CSP, X-Frame-Options, Referrer-Policy, X-Content-Type-Options, sans bavarder (server, x-powered-by) ? | weekly | cliquet (lower) | 15 s | Un en-tête a disparu : nginx (DEPLOY.md) ou next.config — le remettre dans le même lot. |
sec.semgrep_full | Le scan semgrep complet (OWASP, nodejs, react, nextjs) sur tout l'arbre rend-il des findings ERROR ? | weekly | cliquet (lower) | 300 s | Un finding ERROR de plus : le lire avec SECURITY.md §5, corriger ou écrire l'exception dans .semgrepignore avec la raison. |
judge.review | La revue par modèle a-t-elle tourné cette semaine, et une dimension est-elle passée sous 5 ? | daily | rouge si value > 8 | 1 s · sonnet-5 | Revue absente : lire le run « Revue hebdomadaire » (clé API ? périmètre refusé ?). Note basse : lire reviews/<semaine>.md — la preuve citée dit quel fichier. |