Journal des versions

Ce qui a changé dans Veille.

← Tous les modules

17 septembre 2026
en cours

Ce qui se repetait, ce qui se taisait, et ce qui mentait

SEO & LLMCronVeilleStats

  • L’audit repetait les memes 61 pages, et le disait autrement.Un passage explore soixante pages, plus l’accueil. Le code affirmait — et l’ecran l’affichait — que les autres « passeront aux prochains audits ». C’etait faux : la file repartait de la tete du sitemap a chaque fois. Mesure sur un site de 1 279 adresses : deux audits consecutifs, 61 pages chacun, **61 en commun sur 61**. Les 1 218 autres n’avaient jamais ete vues et ne l’auraient jamais ete. Chaque passage est desormais coupe en deux : la moitie pour relire les pages qui avaient un defaut — une page reparee est donc revue au passage suivant, et non au vingtieme — l’autre moitie pour decouvrir. Verifie apres deploiement : 28 pages en commun au lieu de 61, et 154 adresses distinctes vues au lieu de 61.
  • Un sitemap declare ailleurs est un sitemap.Un site declarait le sien sur une fonction hebergee chez un tiers. On ecartait tout sitemap qui n’etait pas sur le domaine audite : on sautait donc le seul sitemap du site, puis on concluait « aucun sitemap trouve, ni declare dans le robots.txt » — a cote d’un autre constat qui disait « ton robots.txt declare un sitemap ». Deux verdicts contraires sur le meme ecran, et c’est celui qui accuse qu’on croit. Declarer un sitemap dans son robots.txt EST l’autorisation de le lire la ou il est. Et quand rien n’est declare, on essaie aussi `sitemap_index.xml` et `wp-sitemap.xml`, que posent les deux outils les plus installes du web.
  • La passe de preuve sondait plus de domaines que sa borne.Un test tombait une fois sur trois, jamais seul. On l’a reecrit trois fois en accusant l’ordre des fichiers, puis la portee de l’assertion. Le symptome n’avait pourtant jamais bouge : trois lignes rendues pour une borne a deux. La sous-requete d’un `IN` peut etre **re-executee** par PostgreSQL, une fois par ligne examinee ; chaque re-execution applique bien la borne, mais pas sur les memes lignes, parce que l’ordre laissait des ex aequo. La correction tient en deux parties dont aucune ne suffit : une CTE `MATERIALIZED`, et un tri qui ferme les ex aequo. Ce que ca protegeait : cette passe sonde des serveurs qui ne sont pas les notres, et depasser sa borne c’est frapper plus fort que promis chez quelqu’un d’autre.
  • Bloquer un robot qui cite et un robot qui entraine n’est plus la meme nouvelle.Un utilisateur a mesure, sur son site, que deux robots d’entrainement recevaient un 403 de son CDN pendant que les quatre robots de citation passaient. Notre audit annoncait « serieux » — et l’urgence n’existait pas : il ne perdait aucune citation ce jour-la, il perdait sa presence dans les corpus des prochains modeles. « Nous avons failli courir », a-t-il ecrit. Une alerte qui fait courir pour rien apprend a ne plus courir, et c’est celle d’apres qui se paie. Citer refuse reste serieux ; entrainer seul refuse devient une attention, avec le moyen de la faire taire si c’est un choix. On sonde cinq robots au lieu de trois, dont trois qui citent : sans eux, la distinction n’etait pas mesurable.
  • Une tache qui n’a jamais demarre se signale. Une fois.Depuis qu’une tache surveillee n’alerte plus tant qu’aucun battement n’est arrive, en creer huit d’un coup ne coute plus une alerte. Mais un cablage faux la laissait en attente **pour toujours**, dans un silence parfaitement paisible : le module dont le metier est de detecter le silence etait le seul a ne pas voir celui-la. C’est l’utilisateur qui l’a vu, pas nous. Trois echeances manquees sans le moindre battement, et un message au libelle distinct — « n’a jamais demarre », pas « ne donne plus signe de vie ». Ce ne sont pas les memes nouvelles : l’une fait relire les journaux du serveur, l’autre la cle de battement.
  • Un essai a blanc pour eprouver un cablage sans laisser de trace.`?essai=1` sur l’adresse de battement repond exactement comme un vrai battement — 200, 404, 429 — et n’ecrit rien. Le mode « execute » avait son essai depuis longtemps ; « monitor », qui demande pourtant le plus de cablage, n’avait rien. Un utilisateur a donc fait la seule chose possible : pinguer une tache en pause. Nous l’avons armee, et son essai a laisse dans l’historique une ligne qui ressemble a une vraie execution.
  • Sortir de pause recalcule l’echeance.Elle restait figee a sa valeur du moment de la mise en pause. Mesure par un utilisateur : une tache horaire relancee a 14 h 12 annoncait encore une prochaine execution a 8 h 07, six heures et demie dans le passe. En mode « execute » le worker rattrape ; en « monitor » personne ne rattrape, et c’est nous qui comparons une heure attendue a une heure reelle. Le module dont le metier est de juger un retard se trompait de reference.
  • L’audit passe de neuf secondes a deux et demie.Soixante et une pages lues l’une apres l’autre font neuf secondes, pendant lesquelles le bouton ne repond pas et on reclique. Quatre pages a la fois, pas quarante : on lit le site de quelqu’un d’autre, et soixante requetes simultanees sur un mutualise peuvent le faire tomber — on serait alors la panne qu’on pretend mesurer. Et tous les boutons du produit portent desormais un disque de chargement, en six lignes de JavaScript qui se dégradent proprement : sans lui, il ne se passe rien de plus qu’avant.
  • LeTock mesure enfin sa propre machine.Il surveillait les serveurs de ses clients et pas le sien. L’ecran d’exploitation repondait a « quand faudra-t-il grandir » par un calcul de cout — exact, et dans une unite qui n’est pas celle de la question : on ne sait pas si cinq euros de volume font transpirer deux coeurs. Charge, memoire, disque et taille de base sont relevees **chaque seconde** et gardees chaque minute, en gardant le maximum et non la valeur de l’instant, qui raterait un pic de trois secondes. Trois fenetres, trois questions : une heure a la seconde pour la forme d’un pic, vingt-quatre heures a la minute pour savoir a quelle heure ca travaille, sept jours a l’heure pour savoir si ca monte.
  • La jauge « la plus pleine » n’en designait aucune.La tuile annoncait « runs d’agents — 1 % du quota » quand la plus pleine etait « audits de pages — 5 % ». Deux defauts empiles, dont le premier est invisible a la lecture : `compte::text AS compte … ORDER BY compte` fait trier PostgreSQL sur le **texte**, parce qu’un nom d’ORDER BY se resout sur les alias de sortie avant les colonnes. En ordre lexicographique, « 93 » passe devant « 2310 ». Et meme trie juste, « le plus gros compte » n’est pas « la plus pleine jauge » : les plafonds varient d’un facteur cent d’un poste a l’autre.
  • L’exploitation prend les formes des stats.Elle posait ses chiffres en liste et ses trente jours en barres, pendant que le module Stats — qui repond aux memes questions sur un site au lieu de tous — avait un bandeau de tete, une courbe d’aire, un anneau et un tableau trie. Deux grammaires visuelles pour une seule idee : savoir lire un ecran n’aidait pas a lire l’autre. La jauge de quota n’utilise volontairement pas le composant Jauge : il colore en vert ce qui approche de cent pour cent, parce qu’il a ete ecrit pour des scores — et un quota a 91 % est l’inverse d’une bonne nouvelle.
  • Le site parle anglais.Le francais reste a la racine, l’anglais vit sous `/en` : aucun lien existant ne casse, aucune redirection, aucun classement perdu. Le francais est la **langue de reference** et non une traduction — son catalogue definit le type, et toute autre langue doit le satisfaire, donc une cle oubliee est une erreur de compilation qui nomme le fichier, pas un trou a l’ecran decouvert par un visiteur. Chaque page porte son canonique dans sa langue et les liens vers les autres ; sans eux, un moteur voit deux adresses voisines, en choisit une, et l’autre disparait.
  • Un selecteur, un domicile.Onze selecteurs de la feuille de style etaient declares deux fois au meme niveau. La seconde gagne, et personne ne le sait en lisant la premiere : on lisait « cette liste est une rangee » et l’element etait une grille, parce que quatre mille lignes plus bas quelqu’un avait reecrit la regle. Du code mort qui a l’air vivant est pire que du code mort — il repond a la question qu’on se pose, et il repond faux. Et quatre classes d’evolution — « +18 % », « −12 % », « = », « nouveau » — n’avaient aucun style du tout.
Ce que ça change pour ton coderupture
  • Un alias de chemin `@/` remplace 609 imports relatifs vers `src/`, qui vivaient a six profondeurs differentes. Sans lui, toute reorganisation se fait a l’arithmetique de « ../ » — exactement le genre de reecriture qui casse une ligne sur cinquante sans qu’aucun test ne le voie.
  • Rupture. `POST /api/v1/taches` accepte `projet` — par nom, par domaine ou par identifiant — et `GET /api/v1/taches?projet=` filtre. Le champ etait accepte et jete en silence depuis des mois : la colonne existait, elle n’etait ecrite nulle part.
  • La creation de tache rend `avertissements` : nuits de changement d’heure sautees ou doublees, mois sans declenchement, et le fuseau laisse implicite. `/api/v1/analyser` les calculait depuis toujours et la creation n’en disait rien — poser une tache sure demandait deux appels, dont un que personne ne fait.
  • Le cout d’un audit passe de sept a neuf requetes : deux sondes d’identite de plus, pour distinguer les robots qui citent de ceux qui entrainent.
  • La suite de tests refuse de tourner a deux exemplaires sur la meme base : un verrou consultatif le dit au lieu de laisser deux executions se vider les tables mutuellement. Mesure une fois le soupcon venu — 263 tests rouges a deux suites, 1703 verts seul.
15 septembre 2026

Un solde pour dépasser, un badge pour agrandir, et des jauges revues à la hausse

MailStatsVeille

  • Les jauges montent, beaucoup.L’audience passe de 18 000 à 60 000 par mois sur le gratuit, de 128 000 à 360 000 sur Solo, de 345 000 à 980 000 sur Équipe. Les e-mails passent de 110 à 1 000, de 2 200 à 15 000, de 7 500 à 50 000. Deux coûts unitaires étaient faux — un événement d’audience et un envoi d’e-mail — et tout le monde payait cette erreur en plafonds trop bas.
  • Un quota atteint n’arrête plus tout.Le solde prend le relais, au tarif unitaire du poste. Un euro achète 50 000 exécutions, 400 000 événements d’audience ou 50 000 e-mails. Le quota mensuel est toujours consommé en premier, et le solde ne se remet jamais à zéro.
  • Le badge donne 10 % de jauge par domaine.Un domaine dont la possession est prouvée et qui affiche le lien « Surveillé par LeTock » relève toutes les jauges de l’équipe de 10 %, au prorata des jours où le lien est en place. Les domaines se cumulent jusqu’à doubler les jauges. Le forfait gratuit y a droit comme les autres.
Ce que ça change pour ton coderupture
  • Rupture. Les quotas de volume ont été multipliés par 1,5, puis rééquilibrés. La règle de marge passe de 60 % à 40 % au pire : on ne laissait consommer que 40 % de ce qui était payé, par prudence, et un plafond jamais atteint ne coûte rien.
  • Nouvelle table `team_solde`, et `consommer()` puise dedans quand le mois est plein. La réponse porte alors `surSolde: true` et `microEurosDebites`. Chaque mouvement est journalisé dans `solde_mouvements`.
  • Nouvelle route `/r/<clé-du-domaine>` : la cible du badge. Elle ne pose aucun cookie et n’enregistre rien — l’attribution passe par la présence du lien sur la page, constatée une fois par jour, pas par qui a cliqué.
  • `limiteDe(teamId, poste)` prend un troisième argument facultatif, l’instant, pour calculer le prorata du badge. Le code existant n’a rien à changer.
  • Le coût d’une alerte passe de 180 à 26 micro-euros, celui d’un événement d’audience de 4 à 1,5, celui d’un envoi de 20 à 12. Le premier était justifié par un prestataire facturé au message, que Tock n’emprunte plus depuis qu’il expédie lui-même.
14 septembre 2026

Auth, le tableau de bord, des quotas qui s’appliquent, et une notice pour les IA

AuthSignauxStatsCronMailUptimeVeilleSEO & LLMErreursIA

  • Les quotas s’appliquent : ce qui était annoncé sur la page Tarifs et ce que le produit laissait faire étaient deux choses différentes — un forfait Équipe à qui l'on promettait cent tâches en obtenait cinq. Chaque forfait a maintenant ses quotas, appliqués au geste près, et un test fait échouer la suite si un forfait cesse d'être rentable quand un abonné le consomme à fond.
  • Ce que tu consommes se voit : huit jauges sur ta page Mon compte, remises à zéro le 1er. Avant, le premier signe qu'un plafond existait était un refus.
  • Une notice pour les assistants de code : toute la plateforme en un fichier, à l'adresse /notice.md — les modules, chaque route, les quotas, les pièges, et ce que Tock ne fait pas. Elle est fabriquée à l'instant où on la demande, donc elle ne peut pas être en retard sur le produit, et elle commence par dire à l'assistant qui la lit d'aller la rechercher à chaque session plutôt que de se fier à une copie.
  • Donne les commandes à ton IA : sur le tableau de bord, tu coches ce que tu autorises — regarder, créer des tâches, envoyer des e-mails — et tu repars avec la clé **et** le texte à coller dans ta conversation : ce qui est permis, ce qui ne l'est pas, et quoi faire d'un refus. Approuver une validation humaine n'est jamais proposé à un agent : une validation qu'il peut s'accorder lui-même n'en est plus une.
  • Auth : Tock devient fournisseur d'identité pour tes applications. Un vrai serveur OpenID Connect — code d'autorisation avec PKCE exigé, rotation des jetons, signature RS256 que tes applications vérifient sans nous appeler, donc notre panne ne devient pas la tienne. Tes utilisateurs se connectent sans mot de passe, sur un écran qui porte ton nom et pas le nôtre. Le flux implicite et le flux par mot de passe sont refusés : ils ont été retirés des recommandations, les proposer serait offrir une porte qu'on sait mauvaise.
  • Tes utilisateurs ne sont pas nos comptes : ils vivent dans une table à part, cloisonnés par projet. Deux tables plutôt qu'un drapeau — un drapeau finit toujours par être oublié dans une clause de filtrage, et ce jour-là l'utilisateur d'un client entre dans le compte d'un autre.
  • Un tableau de bord : ce qui demande attention sur tous tes projets d'un coup d'œil, cumulé ou projet par projet. C'est là que tu arrives en te connectant. Dix requêtes que tu aies un projet ou dix — mesuré, pas supposé.
  • Stats s’explore : cliquer un pays, une source, une page filtre tout l'écran. Treize dimensions, combinables, avec exclusion, et tout dans l'adresse — donc partageable. Les dix répartitions étaient des listes mortes ; ce sont des portes.
  • Stats compte enfin l’argent : la valeur envoyée avec un événement n'était jamais sommée. Revenu par source, par page, par campagne, panier moyen, revenu par visiteur. Des objectifs déclarables avec leur taux de conversion, attribués au premier contact du visiteur — sinon tout revient à l'accès direct.
  • Entonnoirs, parcours, retours : où les gens tombent, par quel chemin ils passent, qui revient. Les retours disent d'abord ce qu'on ne peut pas mesurer : l'empreinte d'un visiteur est jetée chaque nuit, donc personne — nous compris — ne relie une visite de mardi à une visite de mercredi.
  • Signaux : le module qui manquait, et qui est la thèse du produit. Chaque module dépose ce qu'il constate dans un journal commun ; quand deux modules différents constatent quelque chose sur le même domaine à moins de trois jours d'écart, l'écran le dit — « tes ventes ont chuté mardi, ton certificat avait expiré lundi ». Aucun outil isolé ne peut produire cette phrase.
  • Une faille d’authentification, corrigée : sans application GitHub configurée, la session réelle était ignorée et tout visiteur devenait le compte de démonstration. En production, une variable d'environnement oubliée ouvrait la plateforme. Le repli de démonstration ne s'active plus hors développement, et la connexion par e-mail n'est plus court-circuitée.
  • Un double envoi d’e-mails, fermé : la file d'envoi était lue sans être réservée. Deux workers remettaient deux fois le même message au destinataire final — une faute irréversible. La réservation est désormais atomique, et cinq autres veilles qui avaient le même défaut avec elle.
  • La clé API ne passe plus par l’URL : elle entrait dans l'historique du navigateur, dans les journaux du proxy et dans l'en-tête de la navigation suivante. Elle transite par un cookie de deux minutes, effaçable d'un bouton.
  • La validation humaine ne s’approuve plus au clavier : « Approuver » était le premier bouton du formulaire, donc la touche Entrée dans le champ de note approuvait l'action d'un agent. Le défaut clavier est maintenant de ne rien décider.
  • Les mesures sont enfin purgées : deux tables annonçaient en commentaire une purge qui n'existait nulle part — les deux plus alimentées du produit. Et quatorze purges tournaient chaque minute sur un index inutilisable, donc en balayage complet. Une migration d'index, et la rétention promise est tenue.
  • Une seule façon de naviguer dans un module : les sections vivaient tantôt dans la barre de gauche, tantôt en onglets dans la page, sans règle. La barre est le seul endroit où l'on navigue dans un module — et elle dit désormais, module par module, ce qui demande à être regardé.
  • Un seul vocabulaire visuel : quatre classes d'en-tête de page, deux rangées de chiffres, trois sortes de carte, six conventions de bouton et trois collisions de styles — dont une qui faisait perdre leur couleur à tous les messages d'erreur du produit. Tout ça vient d'un même socle de composants.
  • Le thème se choisit : l'échappatoire existait dans la feuille de style depuis le début, et rien ne la posait jamais. Clair, sombre, ou comme le système — sans JavaScript, donc sans scintillement.
  • Se déconnecter : il n'existait aucun moyen de sortir de son compte. Sur un poste partagé, c'était un problème.
Ce que ça change pour ton coderupture
  • Les clés d'API portent des **missions** : ce qu'elles ont le droit de faire, geste par geste, coché sur le tableau de bord. Un appel hors de cette liste répond 403 « mission_non_autorisee ».
  • Rupture. Une route d'écriture qui n'est nommée dans aucune mission tombe dans « divers.ecrire », décoché par défaut : **ce qui est ajouté à l'API après la création d'une clé lui est fermé** tant que personne ne l'ouvre.
  • Rupture. Les quotas des forfaits sont appliqués pour de bon, et non plus par des constantes qui ne connaissaient aucun forfait. Un dépassement mensuel répond 429 « quota_atteint » ; les compteurs repartent le 1er.
  • Rupture. L'intervalle minimum entre deux exécutions d'une tâche passe de 5 à 15 minutes sur le forfait gratuit, et dépend désormais du forfait. Une tâche existante n'est pas touchée ; une modification qui repasse sous l'intervalle est refusée.
  • Nouvelle adresse `/notice.md` : toute la plateforme en un fichier, fabriqué à la demande depuis le code. Et `/notice`, la même chose lisible dans un navigateur.
  • `/llms.txt` annonçait un intervalle minimum de 5 minutes écrit en dur, qui était déjà faux. Les quotas qu’il cite viennent maintenant des forfaits.