Audits · août 2026Audit — variables d'environnement a fallback vide

Audit — variables d'environnement a fallback vide

15 aout 2026. Declenche par le defaut ContextIQ (#429) : un badge qui proposait d'installer une extension deja installee, parce que la variable qui commandait la detection n'etait definie nulle part.

15 aout 2026. Declenche par le defaut ContextIQ (#429) : un badge qui proposait d'installer une extension deja installee, parce que la variable qui commandait la detection n'etait definie nulle part.

Le constat en un paragraphe

Le probleme n'est pas le fallback "". Il est legitime : il permet au produit de demarrer sans que chaque integration optionnelle soit configuree. Le probleme est qu'une variable absente peut couper une fonctionnalite sans que personne, ni operateur ni developpeur, ne puisse l'apprendre. Le repo possede pourtant deja l'outil pour le dire, /admin/operations/env-audit, mais il ne voit qu'un tiers du parc.

Chiffres

MesureValeur
Variables declarees dans serverEnv175
Dont fallback ?? ""158
Enregistrees dans le manifeste env-audit.ts56
Invisibles au dashboard operateur119
Invisibles + gatees sans aucun log ni throw74
Invisibles + gatees + sans intention ecrite38
Declarees sans aucun consommateur dans src/9

La distinction qui compte

Un fallback vide n'est dangereux que lorsque rien n'enonce ce qui se passe sans la variable. Deux contre-exemples sains, trouves pendant l'audit :

  • NEXT_PUBLIC_WHATSAPP_NUMBER — whatsapp-qr-block.tsx ecrit noir sur blanc : « Falls back to a "coming soon" toast when [...] is not set, the QR still renders so the layout holds ». Comportement voulu, connu.
  • NEXT_PUBLIC_SUPPORT_CHAT_PROVIDER — « Default off: explicit opt-in via env so dev/preview don't ping the provider ». Idem.

Ces deux-la ont un fallback vide et ne sont pas des bugs. La signature du defaut ContextIQ etait autre : aucun commentaire, aucun log, aucune entree de manifeste. Le code sortait simplement de la fonction.

Les 38 a la signature ContextIQ

Invisibles au dashboard, gatees sans log, et sans intention ecrite au point de consommation. Ce n'est pas une liste de bugs confirmes : c'est la liste de celles ou, comme pour ContextIQ, rien ne permet de savoir si l'etat eteint est voulu. Chacune demande une lecture de son consommateur pour trancher.

Les plus exposees, parce qu'elles commandent une surface visible :

VariableCe qu'elle commande
NEXT_PUBLIC_HUME_CONFIG_IDsession vocale @Atlas (bouton d'appel du composer)
NEXT_PUBLIC_HEYO_PROJECT_IDwidget de support Heyo
NEXT_PUBLIC_BASE_URLURLs absolues cote client
INVITATION_CODEacces par code d'invitation
LAUNCH_PHASEphase de lancement affichee
MAX_CONVERSATION_USDgarde-fou de cout par conversation
TRACKING_SYSTEM_PASSWORDacces au systeme de tracking
UPSTASH_REDIS_REST_URL / _TOKENcache Redis (double des cles KV_REST_API_*)

Le reste — cles fournisseurs (AHREFS, SEMRUSH, DATOS, DATAFORSEO...), reglages d'intelligence, verifications de moteurs de recherche, drapeaux de fonctionnalite : est vraisemblablement optionnel par nature, mais aucun ne le dit.

Variables mortes

Declarees dans serverEnv, lues nulle part dans src/ :

AI_MODEL_WEBSEARCH · BOOSTECOM_CORS_ORIGINS · DATABASE_POSTGRES_PASSWORD · DATABASE_POSTGRES_USER · KV_REST_API_READ_ONLY_TOKEN · PORT · SHOPIFY_PARTNERS_API_TOKEN · SHOPIFY_PARTNERS_ORG_ID · SHOPIFY_REDIRECT_URI

Certaines sont injectees par une integration Vercel et legitimement inutilisees cote code (DATABASE_POSTGRES_*, KV_REST_API_READ_ONLY_TOKEN). Les autres meritent un coup d'oeil : SHOPIFY_PARTNERS_* et SHOPIFY_REDIRECT_URI ressemblent a du cablage inacheve.

Ce qui a ete fait

src/test/env-audit-coverage.test.ts — un cliquet, pas un grand nettoyage. Trois invariants :

  1. toute variable de serverEnv a une entree de manifeste, sauf les 119 explicitement derogees ;
  2. la liste de derogation reste honnete (pas d'entree deja enregistree ou plus declaree) ;
  3. le manifeste ne nomme pas une variable que serverEnv ne lit pas, elle serait affichee MISSING a jamais.

La dette est donc gelee : elle peut diminuer, plus grandir. Une nouvelle variable non enregistree fait echouer la suite en nommant la coupable. Verifie empiriquement : sortir une cle de la derogation fait bien tomber le test.

Ce qui reste a faire

  1. Reduire la derogation. 119 entrees a documenter dans env-audit.ts (nom, categorie, severite, description, casse). C'est mecanique mais demande la connaissance metier de chaque variable — par lots, par pilier.
  2. Trancher les 38. Pour chacune : soit ecrire l'intention au point de consommation, soit l'enregistrer au manifeste, soit la supprimer.
  3. Les 9 mortes. Confirmer l'injection Vercel pour les unes, supprimer ou cabler les autres.
  4. La lecon de forme. ContextIQ gatait sur une config ce qui etait une donnee publique : l'ID est dans l'URL du store et dans la barre d'adresse de tout utilisateur. Une valeur non secrete n'a pas a vivre uniquement dans l'environnement : lui donner une constante de repli (ce que fait deja APP_URL dans config/platform.ts) supprime la panne silencieuse a la racine.