D-051 : une exception est du code ou de la configuration, jamais un commentaire #114
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "nicolas-fryder/dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Les trois contrôles à marqueur (http.fetch-brut, config.lecture-hors-module, telemetry.console) sont retirés avec leurs marqueurs // eqs-*:autorise. Les règles passent dans les profils ESLint de @eqs/tooling (fetch nu, eqs/process-env, no-console strict côté serveur) ; l'exception à un endroit est un bloc files de configuration (endroits exportés), l'exception à un appel est une API nommée : appel(url, init, { horsContrat }) dans @eqs/http, urlDeConnexion dans @eqs/platform-next, environnementPourSousProcessus dans @eqs/config (les secrets de l'application ne partent plus vers PDAL et CloudCompare). Aussi : tooling.eslint-atteint, bloquant (#100) ; l'audit compte via tooling.fetch-nu et tooling.console et rend null pour une règle que la version installée ne déclare pas. Rien n'est publié : 15 changesets en attente. Porte verte. 🤖 Generated with Claude Code
appel: l'appel sans contrat porte son exception lui-même f0f689a8cdPremier des trois trous du socle que D-051 comble. Un appel sans contrat OpenAPI s'écrivait `fetch(url) // eqs-http:autorise` ; il s'écrit maintenant await appel(url, init, { horsContrat: 'tuiles IGN publiques, sans contrat' }) La raison est une donnée obligatoire (vide, elle lève avant tout appel). Une cible déclarée est refusée : `appel` ne contourne pas un contrat. Et l'exception s'observe en production — le span porte `eqs.hors_contrat`, l'hôte et le chemin. ## Deux choix, et pourquoi **La sémantique de `fetch`, pas celle du mutator.** Le mutator lit du JSON, refuse les redirections et plafonne la taille : c'est le transport d'un contrat. Les appels hors contrat mesurés dans la flotte sont des téléchargements de tuiles LiDAR binaires. `appel` rend la `Response` brute, si bien que migrer un `fetch` nu est un renommage, rien de plus. **Pas l'URL complète sur le span.** Une API tierce met parfois sa clé dans la requête ; la poser sur un span l'enverrait au collecteur. Un test le fixe en posant `?cle=SECRET` et en exigeant qu'elle n'apparaisse nulle part. Six tests, éprouvés en cassant le refus de cible puis l'exclusion de la requête : chaque fois, exactement le test qui fixe la propriété rougit. Noté pour l'étape du retrait : le cahier dit que le compte de `http.fetch-brut` est remonté dans `eqs-audit.json` (`outgoing.rawHttpCalls`). La vue de flotte le consomme ; il faudra le remplacer, pas seulement l'effacer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>urlDeConnexion: la connexion sociale sortie du composant SignIn f63b762309Deuxième trou de D-051. Un satellite réécrivait l'appel à better-auth en `fetch` nu pour obtenir l'adresse de connexion, parce que `SignIn` l'enfermait dans un composant qui navigue. La fonction rend l'adresse et ne navigue pas ; `SignIn` s'en sert, si bien qu'il n'y a qu'un seul chemin vers better-auth. Elle corrige un défaut du composant au passage : il lisait le corps sans vérifier le statut, donc un refus du serveur s'affichait comme une indisponibilité. ## Une crainte infondée, et une mesure fausse avant la bonne `nuage` justifiait sa réécriture par un bundle navigateur pollué : le point d'entrée client tirerait `node:async_hooks`. Ma première mesure lui a donné raison — elle suivait les imports par expression régulière sur le texte, et elle a pris pour un import une phrase de COMMENTAIRE contenant `import { ApiError } from '@eqs/http'`. Refaite par l'arbre syntaxique de TypeScript : ni `@eqs/platform-next/client` ni `@eqs/http/browser` n'atteignent un seul module `node:`. La crainte était infondée, et mon instrument venait de commettre exactement la faute que D-051 retire du socle — lire un commentaire comme s'il portait du sens. Le nom diffère de celui annoncé (`seConnecter`) : une fonction qui rend une adresse sans connecter personne ne peut pas s'appeler ainsi. Quatre tests, le parcours social n'en avait aucun. Éprouvé en retirant la vérification du statut : le test du refus rougit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Troisième trou de D-051, et le seul que les commentaires cachaient au point de ne pas en porter. Un satellite passait `env: { ...process.env }` à deux binaires géospatiaux tiers, avec un commentaire disant que c'était voulu. Pour le système, oui. Pour `AUTH_SECRET`, `MS_CLIENT_SECRET` et `DATABASE_URL`, qui partaient avec, personne ne l'avait décidé — et rien ne le montrait. `environnementPourSousProcessus` rend l'environnement du système moins la configuration de l'application : les clés du schéma sont retirées. Un secret qu'un enfant doit vraiment recevoir s'ajoute par `ajouter`, écrit dans le code. C'est la forme exacte de ce que D-051 dit : l'exception est portée par un nom de fonction, cherchable, typé, et qui dit ce qu'il fait. Ici, en plus, le nom force une frontière que le commentaire laissait ouverte. Une directive `eslint-disable` posée par réflexe dans le socle a été retirée avant le commit : la règle n'existe pas encore, et le module de configuration est un ENDROIT autorisé à lire l'environnement — ce sera de la configuration à l'étape suivante, pas une directive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>updateUserInfoOnLink(le rôle est déjà protégé) #113