Le texte explore deux approches pour gérer les dépendances lors de tests locaux de services communiquant avec S3 dans une application Symfony. La première question technique concerne l'utilisation de class: versus alias: pour redéfinir un service. L'auteur illustre qu'un alias peut être préférable car il permet de pointer vers une autre définition de service sans pour autant le réinstancier directement, évitant ainsi des erreurs de construction comme le manque d'arguments.
La deuxième question aborde une décision d'architecture : privilégier un "double maison jetable" (un faux service temporaire redirigeant vers le système de fichiers local) plutôt qu'une solution comme MinIO (un conteneur S3-compatible). Cette approche est motivée par la simplicité et la réversibilité, rendant la modification facilement identifiable et supprimable après les tests, notamment grâce au bloc when@dev de Symfony qui permet de scoper la configuration à un environnement spécifique.
En résumé, le choix entre une configuration via class: ou alias: pour substituer un service en environnement de développement, et le type de fausse dépendance utilisé, sont des décisions d'ingénierie qui doivent être adaptées au contexte et aux besoins de réversibilité du processus de développement. L'utilisation de blocs de configuration conditionnels comme when@dev facilite l'intégration et la suppression temporaire de ces adaptations pour les besoins de recettes et de tests.
Le composant Symfony ObjectMapper simplifie la conversion entre différents objets, notamment pour transformer des DTOs (Data Transfer Objects) en entités ou vice versa. Cette approche permet de découpler les données d'entrée et de sortie d'une API des modèles internes, ce qui est particulièrement utile lors de la gestion de code existant ou de l'implémentation d'architectures hexagonales.
L'ObjectMapper agit comme un traducteur, prenant les données d'un objet source et les convertissant directement dans le format d'un objet cible, sans passer par une étape intermédiaire sous forme de tableau. Cette méthode est plus simple et efficace que l'utilisation du composant Serializer de Symfony, qui nécessitait une normalisation en tableau puis une dénormalisation, impliquant potentiellement plus de configuration.
L'utilisation de DTOs est recommandée pour séparer clairement les responsabilités. Tandis que les entités sont liées à la logique métier et à la persistance, les DTOs définissent les données à exposer ou à recevoir à une interface spécifique, offrant ainsi un contrôle sur ce qui traverse les frontières de l'application et améliorant la maintenabilité.
L'application Symfony a souffert d'épuisement de mémoire, provoquant des plantages de conteneurs nocturnes. Le développeur a d'abord suspecté une fuite de mémoire, mais l'analyse a révélé que le problème provenait de requêtes gourmandes en ressources, chacune consommant jusqu'à 512 Mo. Ces requêtes saturaient rapidement le pool de travailleurs PHP-FPM, entraînant l'indisponibilité du site.
Face à l'augmentation du contenu, le développeur a mis en place des outils de surveillance pour identifier les routes problématiques. Il a découvert cinq schémas récurrents dans Doctrine, tous contribuant à la consommation excessive de mémoire. La première cause identifiée était une hydratation complète des entités Doctrine lorsque seules quelques colonnes étaient nécessaires, comme dans le cas de la génération du sitemap.
Cette surconsommation de mémoire a été résolue en optimisant le code pour éviter l'hydratation inutile des entités. Le développeur a instrumenté son application avant de toucher au code, ce qui lui a permis de cibler précisément les problèmes. L'objectif était de réduire la quantité de données chargées et traitées par chaque requête, afin de prévenir l'épuisement de la mémoire.
L'application Symfony a rencontré des problèmes de mémoire dus à des requêtes gourmandes, saturant le pool de workers. Après analyse, cinq schémas récurrents dans Doctrine ont été identifiés comme responsables, notamment une hydratation complète des entités là où seule une partie des données était nécessaire. L'optimisation du code pour réduire la consommation de mémoire par requête a permis de résoudre le problème.
L'article aborde le conflit entre le principe d'immuabilité de l'event sourcing et le droit à l'effacement du RGPD. Les approches traditionnelles comme la réécriture ou la suppression physique des événements sont jugées destructrices pour l'intégrité du système.
La solution proposée repose sur le concept de "forgettable payloads" : les données personnelles ne sont plus stockées directement dans les événements immuables, mais dans un espace de stockage séparé et mutable. L'événement conserve son identité et une référence vers ces données, mais la suppression du compte utilisateur implique de rendre ces données inaccessibles, sans altérer le flux d'événements.
Cette inaccessibilité est concrètement réalisée par le "crypto-shredding" des données : chaque charge utile est chiffrée avec une clé unique, et le processus d'effacement consiste à détruire cette clé. Si aucune copie de clé ou donnée en clair ne subsiste ailleurs, les données chiffrées deviennent indéchiffrables, honorant ainsi la demande d'effacement sans compromettre l'historique des événements.
Le composant Symfony Runtime, introduit dans Symfony 5.3, a modernisé le démarrage des applications PHP en séparant la logique d'initialisation de celle du contrôleur frontal. Auparavant, le fichier public/index.php contenait une grande partie de l'infrastructure de l'application, ce qui posait des problèmes de maintenance et de propagation des mises à jour du code de démarrage.
Grâce à Runtime, le code d'amorçage est désormais géré par un composant Composer dédié, permettant ainsi des mises à jour plus fluides via la gestion des dépendances. Cette architecture découplée est particulièrement avantageuse car elle permet aux applications Symfony de s'exécuter dans divers environnements, qu'il s'agisse des serveurs PHP traditionnels (PHP-FPM) ou de solutions plus modernes comme FrankenPHP, Swoole ou ReactPHP, sans modifier le contrôleur frontal.
Le principal avantage architectural de Symfony Runtime réside dans sa capacité à désolidariser le processus de démarrage de l'application de son modèle d'exécution. Cela signifie qu'une même application peut s'adapter à différents types d'environnements d'exécution, y compris les processus PHP à longue durée de vie, sans nécessiter de réécrire sa logique d'initialisation. Cette flexibilité ouvre la voie à une portabilité accrue des applications Symfony sur une gamme plus large de plateformes.
Symfony 8.1 introduit la variable d'environnement FRANKENPHP_RESET_KERNEL pour résoudre un problème de fuite d'état dans les applications PHP fonctionnant en mode "worker" avec FrankenPHP. Ce mode maintient le processus PHP en vie entre les requêtes pour améliorer les performances, mais crée un risque que l'état de services persistants ne soit pas correctement réinitialisé, ce qui peut entraîner une incohérence ou une exposition involontaire de données entre les requêtes.
Traditionnellement, chaque requête HTTP dans PHP démarrait avec un environnement isolé, garantissant que l'état de l'application était remis à zéro. Le mode worker de FrankenPHP, quant à lui, réutilise le noyau et les services Symfony, offrant un gain de vitesse significatif mais introduisant le risque de propagation d'état non désiré si les services ne sont pas explicitement réinitialisés.
Pour pallier ce risque, Symfony propose l'interface ResetInterface qui permet aux services de vider leur état entre les requêtes. Cependant, cette approche dépend de la bonne implémentation par tous les services, y compris ceux de tiers ou le code hérité. FRANKENPHP_RESET_KERNEL agit comme une mesure de sécurité supplémentaire, garantissant que le noyau est réinitialisé automatiquement, ce qui renforce la robustesse et la sécurité des applications PHP en mode worker.
Le nouveau command symfony lsp:check résout un problème courant de typographie dans les noms de routes Symfony que les outils d'analyse statique comme PHPStan ne peuvent pas détecter. Ces erreurs, souvent des fautes de frappe minimes, peuvent passer inaperçues lors des revues de code ou des tests automatisés, menant à des bugs en production. Le command analyse les routes, les templates, les traductions et la configuration pour identifier ces erreurs spécifiques à Symfony.
Le command symfony lsp:check est une version autonome des diagnostics déjà présents dans les extensions de langage Symfony pour les éditeurs. Il fonctionne en démarrant l'application dans l'environnement sélectionné pour analyser la configuration et les routes réelles, offrant ainsi une détection précise des erreurs. Il couvre un large éventail de problèmes, incluant les routes inexistantes, les templates manquants, les clés de traduction erronées et les configurations invalides, avec la possibilité de basculer vers une analyse statique si l'exécution du code n'est pas possible en CI.
Visa et Mastercard sont des réseaux de cartes, et non les émetteurs de cartes ou les banques qui fournissent ces cartes aux consommateurs. Ils ne s'occupent pas non plus des processeurs de paiement qui gèrent les transactions sur les terminaux ou en ligne, ni de l'intégration des commerçants.
Leur rôle principal est de relier les titulaires de cartes et les émetteurs aux commerçants et aux acquéreurs afin de faciliter les transactions par carte. Ils exploitent l'infrastructure de télécommunication nécessaire au routage des messages de transaction, coordonnent le transfert de fonds et règlent les transactions entre les parties concernées.
En outre, ces réseaux définissent les règles qui régissent leur écosystème, y compris les procédures de règlement des litiges, et mettent en place des incitations pour encourager l'utilisation de leurs réseaux. Leur infrastructure est conçue pour être hautement sécurisée et résiliente afin d'assurer la fiabilité des transactions.
L'article soutient que la tendance actuelle à diviser les systèmes d'IA en de multiples agents spécialisés, à l'instar des microservices, peut être prématurée et coûteuse. Il souligne que de nombreux agents médiocres ne surpassent pas un seul agent performant, et que la complexité croissante d'un agent unique conduit à une dégradation progressive. Les problèmes majeurs incluent la difficulté de sélectionner le bon outil parmi une liste étendue, la contradiction des instructions dans un unique prompt, et la difficulté de modifier le système sans affecter l'ensemble.
Le moment idéal pour opérer une scission en agents multiples est lorsque ces difficultés deviennent mesurables et nuisibles, et non sur la base d'une esthétique ou d'une tendance. La solution proposée est le schéma "supervisor pattern", où un agent superviseur centralise la classification et le routage des requêtes vers des agents spécialisés. Chaque agent spécialiste est confiné à un domaine unique, disposant de son propre prompt clair, d'un ensemble d'outils limité et distinct, et gérant son propre état de conversation.
Ce modèle permet de retrouver la précision dans le choix des outils et d'éviter les conflits d'instructions, offrant ainsi une meilleure maintenabilité et évolutivité. L'idée principale est de ne pas commencer avec une architecture multi-agents avant que la nécessité ne soit clairement établie par des problèmes concrets liés à la complexité d'un agent unique, puis d'adopter une approche structurée avec un superviseur et des spécialistes.
L'implémentation de Page Objects dans Playwright est une approche pour améliorer la maintenabilité et la réutilisabilité du code de test automatisé. Plutôt que d'interagir directement avec les éléments de l'interface utilisateur dans chaque scénario de test, les Page Objects encapsulent les sélecteurs d'éléments et les actions associées à une page spécifique de l'application web. Cela permet de centraliser la logique de localisation des éléments, rendant les tests plus robustes face aux changements de structure du site.
Playwright propose deux styles de Page Objects : un pour les suites de tests utilisant le runner intégré de Playwright, et un autre destiné à l'intégration dans des frameworks de test externes comme Jest ou Cucumber. Les deux approches s'appuient sur les concepts de fixtures de test, notamment la fixture Page qui fournit un objet pour interagir avec une seule page du navigateur et la notion de Locator pour trouver des éléments de manière fiable grâce aux mécanismes d'attente automatique de Playwright.
La mise en place d'un Page Object implique généralement d'importer les types Locator et Page de la bibliothèque Playwright Test. Ces objets fournissent des méthodes pour sélectionner et manipuler les éléments de l'interface, assurant que les tests sont moins susceptibles de devenir obsolètes en cas de modifications mineures du code HTML de l'application.
Pour mieux comprendre les systèmes complexes, l'auteur a développé une approche utilisant des agents d'IA pour agréger des connaissances réparties entre le code, la documentation et le savoir tacite des équipes. L'objectif est de supprimer la nécessité de réunir plusieurs personnes pour décortiquer le fonctionnement d'un système.
La première tentative consistait en un agent général connecté à des outils comme Notion et GitHub. Bien qu'utile pour des périmètres restreints, cette approche a montré ses limites en matière de fiabilité et de capacité à traverser les frontières des différents domaines d'expertise. Face à ces difficultés, l'auteur a décidé de construire une solution plus robuste et personnalisée.
La seconde tentative, nommée "ruche", implique la création d'un dépôt centralisé regroupant les dépôts de code pertinents via des sous-modules Git. Chaque sous-module est accompagné d'un fichier AGENTS.md fournissant un contexte, formant ainsi une "ruche" d'agents capables d'accéder et de traiter l'information de manière plus efficace.
L'hébergement de son propre serveur de messagerie est désormais réalisable, y compris depuis son domicile, malgré les réticences fréquentes liées aux problèmes de spam et de livraison. L'idée principale est de reprendre le contrôle de ses données et de favoriser la décentralisation d'Internet, en évitant que quelques grandes entreprises ne concentrent toutes les informations.
Pour un hébergement à domicile, certaines conditions techniques sont nécessaires : une adresse IP statique IPv4 non blacklistée, ne pas être derrière un CGNAT, pouvoir modifier le enregistrement PTR de son IP et ouvrir les ports couramment utilisés par les serveurs de messagerie. Les interruptions de service internet sont généralement bien gérées par le système de relai des e-mails, le destinataire ne perdant donc pas de messages lors de courtes indisponibilités.
Plusieurs solutions logicielles existent pour mettre en place un serveur de messagerie, comme docker-mailserver, Stalwart ou Mailcow, offrant différentes approches pour le déploiement. Il est également crucial de configurer correctement les enregistrements DNS (SPF, DKIM, DMARC, MX) de son domaine pour assurer une bonne délivrabilité des e-mails et prévenir le spoofing.
Cet article met en évidence la convergence architecturale entre des frameworks web populaires tels que Spring Boot (Java), Symfony et Laravel (PHP), ainsi que NestJS (Node.js). Malgré leurs langages distincts, ces outils partagent une philosophie commune visant à faciliter la maintenance des applications serveur sur le long terme. Ils s'appuient sur des concepts clés tels que l'injection de dépendances, le routage déclaratif, les patrons de conception de type "repository" et une gestion de configuration adaptable aux différents environnements.
L'auteur illustre cette similarité en comparant des exemples de contrôleurs dans chaque framework. Il observe que l'injection par constructeur, l'isolement des services métiers et la déclaration des routes directement dans le code de la méthode sont des pratiques récurrentes. Cette approche, notamment celle de Spring Boot avec ses "starters" qui simplifient la configuration initiale, rappelle des concepts déjà présents dans l'écosystème PHP, suggérant une influence mutuelle et une standardisation des solutions architecturales pour les applications web modernes.
Cet article relate le processus de migration d'un Fairphone 4 d'Android vers le système d'exploitation /e/OS. L'auteur, dans le cadre de son partenariat avec Commown, a rencontré plusieurs difficultés techniques lors de l'installation via l'installeur web, notamment des problèmes de connexion ADB et de verrouillage du bootloader. L'intervention du support technique de Commown a finalement permis de mener à bien l'installation en ligne de commande.
Ce récit détaille les étapes rencontrées lors de l'installation de /e/OS sur un Fairphone 4, incluant les défis liés à l'installeur web, aux messages d'erreur fréquents et à la nécessité d'une intervention manuelle via adb et fastboot. La collaboration avec le support Commown a été essentielle pour résoudre les blocages.
L'article révèle qu'une instance Yunohost initialement configurée pour être privée derrière une Freebox est devenue accessible publiquement sur Internet. Cette exposition inattendue n'était pas due à un bug des mises à jour de la Freebox ou à des problèmes de certificats.
La cause principale identifiée est l'activation du protocole UPnP IGD (Universal Plug and Play - Internet Gateway Device) sur la Freebox. Ce protocole, lorsqu'il est activé, permet aux appareils connectés d'ouvrir automatiquement les ports nécessaires, contournant ainsi les règles de NAT manuelles mises en place et rendant la machine Yunohost visible de tout Internet.
L'auteur a désactivé cette fonction UPnP IGD pour restaurer la restriction d'accès souhaitée. Il envisage désormais de placer sa machine Yunohost derrière un routeur dédié comme Pfsense ou Opnsense pour renforcer la sécurité.
L'article aborde le problème de la dépendance à des plateformes logicielles américaines comme GitHub, qui, au-delà de la simple gestion de code, représentent des réseaux sociaux et des usines logicielles. La concentration du marché, dominé par GitHub, soulève des questions de souveraineté et de sécurité des données, particulièrement à la lumière de lois américaines comme le Cloud Act et la FISA, qui peuvent contraindre ces plateformes à partager des informations sensibles avec les autorités américaines.
Face à ces risques, l'article explore les alternatives européennes. Il mentionne le self-hosting avec Forgejo, un fork de Gitea maintenu par l'organisation Codeberg, jugé comme la seule option viable dans ce domaine, bien que présentant des défis de maintenance. Pour les solutions hébergées, Codeberg.org est présenté comme une option pour les projets open source, tandis que Tangled.org est mentionné comme un projet prometteur s'appuyant sur ATProto.
En résumé, la dépendance vis-à-vis de GitHub pose des risques liés à la souveraineté des données et aux lois américaines. L'article propose des alternatives européennes comme Forgejo pour le self-hosting et explore des solutions hébergées, tout en soulignant leurs limitations actuelles pour les projets d'entreprise.
L'article explore le concept de "Agentic Coding" en comparant le développement de composants graphiques personnalisés à l'aide de primitives D3 et de la librairie Recharts. L'auteur a découvert que l'approche basée sur les primitives D3 a permis de satisfaire pleinement les exigences de conception complexes, y compris les animations et les comportements spécifiques, sans nécessiter de contournements coûteux.
En contraste, la librairie Recharts, bien que plus rapide pour les cas courants, a rapidement montré ses limites pour atteindre les 20% de personnalisation restants, obligeant à coder du SVG personnalisé et à désactiver des fonctionnalités comme les animations pour contourner des problèmes de compatibilité avec la pile React du projet.
L'auteur redéfinit l'abstraction non pas comme un coût nul, mais comme un travail d'implémentation pré-payé qui offre de la flexibilité en échange. L'histoire du développement web est vue comme une ascension progressive de cette échelle d'abstraction, où chaque étape convertit du travail humain coûteux en dépendances moins chères, mais où les besoins spécifiques finissent par révéler les contraintes de ces abstractions de haut niveau.
Dans une architecture CQRS, la synchronisation entre la base de données de lecture et celle d'écriture est un défi majeur pour éviter la présentation d'informations obsolètes. Une stratégie de synchronisation en deux étapes est nécessaire pour équilibrer la performance de la base de données de lecture et la cohérence de la base de données d'écriture.
Face à des volumes importants de données et à des besoins de recherche performante, comme dans le cas d'une recherche de disponibilités hôtelières, une base de données unique avec de nombreux index peut devenir inefficace. L'adoption d'une architecture CQRS, séparant la gestion des commandes et des requêtes, permet d'optimiser ces aspects en utilisant une base de données dédiée à la lecture, telle que MongoDB, enrichie d'index appropriés.
Pour maintenir la cohérence entre la base de données principale (PostgreSQL) et la base de données de recherche (MongoDB), une approche asynchrone est privilégiée. Les modifications apportées à PostgreSQL sont publiées sur un broker de messages, et MongoDB les traite lorsque sa charge de lecture le permet, garantissant ainsi que les opérations d'écriture restent rapides. Pour pallier les risques liés aux opérations asynchrones, des reconstructions planifiées de la base de données de lecture sont effectuées, généralement pendant les périodes de faible activité, afin d'assurer la mise à jour des données.
-
L'auteur décrit une expérimentation où il délègue la génération de code à des agents basés sur l'IA. Initialement, il agissait comme un intermédiaire, copiant-collant des tickets dans des sessions d'agents pour déclencher leur travail. Cette tâche répétitive l'a conduit à réaliser que la partie réellement créative et intéressante du processus de développement se situait en amont, lors de la spécification des tickets.
Cette évolution s'inscrit dans une progression sur plusieurs années, passant de la complétion de code (Copilot) au dialogue avec les modèles (chat), puis à l'agentique où les IA peuvent modifier des fichiers et exécuter des commandes sous supervision. L'étape actuelle consiste à retirer l'humain de la boucle de déclenchement des agents, transformant son rôle.
Le changement majeur est passé de l'écriture directe de code à la spécification détaillée de ce qui doit être codé. L'expérimentation actuelle vise à pousser cette idée plus loin en retirant l'humain de la seule action de lancer les agents, le rôle du développeur se concentrant désormais sur la définition précise des tâches à accomplir par l'IA.
Ce tutoriel explique comment configurer Fail2ban pour sécuriser Nginx Proxy Manager (NPM) dans un environnement Docker. L'objectif est de bloquer les tentatives d'accès non autorisés, notamment les attaques par force brute sur l'authentification Basic Auth, sans modifier l'image Docker de NPM ni ajouter de conteneur supplémentaire.
La méthode préconisée repose sur l'analyse des logs d'accès de NPM, qui enregistrent les échecs d'authentification HTTP 401. Fail2ban, exécuté sur l'hôte Docker, surveille ces logs pour identifier les adresses IP suspectes et les bannir temporairement des ports 80 et 443. L'approche vise à rester simple (KISS) en utilisant les journaux natifs de NPM et en s'appuyant sur la configuration existante de Fail2ban sur l'hôte.
La procédure implique de localiser le fichier journal d'accès pertinent pour le Proxy Host ciblé, de créer un filtre Fail2ban spécifique pour reconnaître les échecs d'authentification 401 et d'inclure l'adresse IP du client (