<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sylvainbruas</title>
    <description>The latest articles on DEV Community by sylvainbruas (@sylvainbruas).</description>
    <link>https://dev.to/sylvainbruas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1362992%2Fcdfb589f-0bf6-4cb7-9dfa-cfee79713384.webp</url>
      <title>DEV Community: sylvainbruas</title>
      <link>https://dev.to/sylvainbruas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sylvainbruas"/>
    <language>en</language>
    <item>
      <title>BMAD Method et Agent Lattice : structurer la vision produit avec l'IA de bout en bout</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:07:41 +0000</pubDate>
      <link>https://dev.to/aws-builders/bmad-method-et-agent-lattice-structurer-la-vision-produit-avec-lia-de-bout-en-bout-161m</link>
      <guid>https://dev.to/aws-builders/bmad-method-et-agent-lattice-structurer-la-vision-produit-avec-lia-de-bout-en-bout-161m</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpubbzsgfbx9ihuo02qd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpubbzsgfbx9ihuo02qd.webp" alt="BMAD Method et Agent Lattice" width="799" height="503"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Le développement assisté par IA a résolu un premier problème : générer du code rapidement. Mais un deuxième problème, plus fondamental, persiste : &lt;strong&gt;qui définit ce qu'il faut construire, et comment s'assurer que l'IA respecte cette vision ?&lt;/strong&gt; La méthode BMAD et l'outil AWS &lt;a href="https://github.com/aws-samples/sample-e2e-product-development-with-kiro" rel="noopener noreferrer"&gt;sample-e2e-product-development-with-kiro&lt;/a&gt; apportent chacun une réponse à cette question, avec des approches complémentaires qui s'inscrivent pleinement dans la logique de l'&lt;a href="https://dev.to/blog/2026/07/kiro-starter"&gt;AI-DLC&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  BMAD : une équipe virtuelle pour piloter le cycle produit
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Le problème de la dérive contextuelle
&lt;/h3&gt;

&lt;p&gt;Quand vous utilisez un agent IA dans un IDE — que ce soit &lt;a href="https://www.cursor.com/" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;, &lt;a href="https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; ou &lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; — chaque nouvelle session repart à zéro. L'agent ne sait plus pourquoi telle décision architecturale a été prise, quels compromis ont été acceptés, ou quels cas limites ont été identifiés. C'est ce que la communauté appelle la &lt;strong&gt;dérive contextuelle&lt;/strong&gt; : un code fonctionnel qui s'éloigne progressivement de la vision produit initiale.&lt;/p&gt;

&lt;p&gt;La méthode &lt;a href="https://github.com/bmad-code-org/BMAD-METHOD" rel="noopener noreferrer"&gt;BMAD&lt;/a&gt; (Breakthrough Method of Agile AI-Driven Development) attaque ce problème frontalement. Au lieu de traiter l'IA comme un assistant généraliste, BMAD orchestre des &lt;strong&gt;agents spécialisés&lt;/strong&gt; — chacun avec un rôle précis, une place définie dans le workflow, et des livrables documentés.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les agents BMAD : des personas avec une mission
&lt;/h3&gt;

&lt;p&gt;BMAD définit plus de 12 agents spécialisés, dont six rôles principaux :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Persona&lt;/th&gt;
&lt;th&gt;Responsabilité&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Analyst&lt;/td&gt;
&lt;td&gt;Mary&lt;/td&gt;
&lt;td&gt;Brainstorming, recherche marché, brief projet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product Manager&lt;/td&gt;
&lt;td&gt;John&lt;/td&gt;
&lt;td&gt;PRD, épics, stories, validation produit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architect&lt;/td&gt;
&lt;td&gt;Winston&lt;/td&gt;
&lt;td&gt;Architecture système, tech stack, APIs, schémas DB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer&lt;/td&gt;
&lt;td&gt;Amelia&lt;/td&gt;
&lt;td&gt;Implémentation, code review, sprint planning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UX Designer&lt;/td&gt;
&lt;td&gt;Sally&lt;/td&gt;
&lt;td&gt;Specs UX, patterns d'interaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tech Writer&lt;/td&gt;
&lt;td&gt;Paige&lt;/td&gt;
&lt;td&gt;Documentation technique&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Chaque agent est un fichier Markdown/YAML qui encode sa persona, ses commandes et ses dépendances. L'activation suit un template structuré : chargement du contexte persistant, adoption de la persona, puis exécution de la tâche.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quatre phases, des artefacts durables
&lt;/h3&gt;

&lt;p&gt;BMAD structure le développement en quatre phases successives :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Analyse&lt;/strong&gt; — Brainstorming, recherche, brief produit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planification&lt;/strong&gt; — PRD, spécifications UX, architecture&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conception&lt;/strong&gt; — Architecture détaillée, design système&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implémentation&lt;/strong&gt; — Développement story par story, code review, rétrospective&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le point clé : chaque phase produit des &lt;strong&gt;artefacts versionnés dans Git&lt;/strong&gt; (PRD, documents d'architecture, fichiers story) qui deviennent la source de vérité du projet. Quand l'agent Developer ouvre une nouvelle session, il ne repart pas à zéro — il lit le fichier story qui contient tout le contexte nécessaire à l'implémentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Lattice : le Design Thinking piloté par l'IA dans Kiro
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Un sample AWS qui va plus loin qu'un exemple
&lt;/h3&gt;

&lt;p&gt;Le repository &lt;a href="https://github.com/aws-samples/sample-e2e-product-development-with-kiro" rel="noopener noreferrer"&gt;sample-e2e-product-development-with-kiro&lt;/a&gt; publié par AWS Labs n'est pas un simple tutoriel. C'est un &lt;strong&gt;framework complet&lt;/strong&gt; — baptisé Agent Lattice — qui orchestre un processus de Design Thinking de bout en bout, directement dans l'IDE Kiro.&lt;/p&gt;

&lt;p&gt;Agent Lattice se compose de deux éléments :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Le runtime&lt;/strong&gt; (&lt;code&gt;.al/&lt;/code&gt;) : un orchestrateur qui gère les rôles, workflows, gates et scripts, avec des modules pluggables pour le Design Thinking et la génération de specs Kiro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Les extensions IDE&lt;/strong&gt; : un plugin de visualisation qui affiche la progression des phases dans une sidebar dédiée&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Le workflow Design Thinking complet
&lt;/h3&gt;

&lt;p&gt;L'outil guide l'utilisateur à travers les cinq phases classiques du Design Thinking, orchestrées par des skills Kiro :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Empathize&lt;/strong&gt; (&lt;code&gt;/al-dt-workflow-empathize&lt;/code&gt;) — Interviews utilisateurs, empathy maps, personas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define&lt;/strong&gt; — Carte d'affinité, insights, questions "How Might We"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ideate&lt;/strong&gt; — Brainstorming structuré, évaluation des concepts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype&lt;/strong&gt; — User flows, wireframes, spécifications d'interaction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test&lt;/strong&gt; — Plans de test, métriques, validation des hypothèses&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;À la fin du processus, un module &lt;strong&gt;Kiro Bridge&lt;/strong&gt; transforme automatiquement les artefacts de Design Thinking en specs Kiro natives (requirements → design → tasks), prêtes pour l'implémentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  L'impersonation de rôles
&lt;/h3&gt;

&lt;p&gt;Un mécanisme original d'Agent Lattice : la commande &lt;code&gt;/al-impersonate&lt;/code&gt; permet à l'IA d'adopter un rôle spécifique (designer, ingénieur, product manager, UX researcher, market researcher) pendant une phase donnée. Chaque rôle dispose de son propre fichier de steering qui cadre les réponses de l'IA selon l'expertise attendue.&lt;/p&gt;

&lt;h2&gt;
  
  
  L'intérêt pour la vision produit et l'AI-DLC
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Combler le fossé entre intention et implémentation
&lt;/h3&gt;

&lt;p&gt;L'AI-DLC, tel que &lt;a href="https://aws.amazon.com/pt/blogs/devops/ai-driven-development-life-cycle/" rel="noopener noreferrer"&gt;formalisé par AWS&lt;/a&gt;, repositionne l'humain sur la direction stratégique tandis que l'IA exécute. Mais ce modèle suppose que la direction stratégique est &lt;strong&gt;clairement articulée et accessible&lt;/strong&gt; à l'agent d'implémentation. C'est précisément le maillon faible de la plupart des outils actuels.&lt;/p&gt;

&lt;p&gt;BMAD et Agent Lattice adressent ce fossé de deux manières complémentaires :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BMAD&lt;/strong&gt; structure la &lt;strong&gt;chaîne de documents&lt;/strong&gt; (brief → PRD → architecture → stories) qui encode les décisions produit de manière durable et versionnable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Lattice&lt;/strong&gt; structure la &lt;strong&gt;phase d'exploration&lt;/strong&gt; (empathie → problème → idéation → prototype → test) qui précède la rédaction des specs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensemble, ils couvrent l'intégralité du spectre : de la compréhension utilisateur jusqu'au code déployé.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le développeur comme Tech Lead, pas comme exécutant
&lt;/h3&gt;

&lt;p&gt;Dans un AI-DLC structuré par ces outils, le rôle du développeur change fondamentalement. Il ne passe plus son temps à écrire du code répétitif. Il :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Valide les personas&lt;/strong&gt; générées par la phase Empathize&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbitre les décisions architecturales&lt;/strong&gt; proposées par l'agent Architect&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review les stories&lt;/strong&gt; avant de lancer l'implémentation automatique&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approuve les gates&lt;/strong&gt; entre chaque phase du workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C'est un rôle de &lt;strong&gt;curateur et de validateur&lt;/strong&gt; — exactement la redistribution de l'effort cognitif que promet l'AI-DLC.&lt;/p&gt;

&lt;h3&gt;
  
  
  Artefacts versionnés : la mémoire du projet
&lt;/h3&gt;

&lt;p&gt;Le bénéfice le plus tangible de ces deux approches : &lt;strong&gt;le projet a une mémoire&lt;/strong&gt;. Les PRD, les documents d'architecture, les empathy maps, les fichiers story — tout vit dans Git. Un nouveau développeur qui rejoint le projet peut comprendre non seulement &lt;em&gt;ce que&lt;/em&gt; le logiciel fait, mais &lt;em&gt;pourquoi&lt;/em&gt; il a été conçu ainsi. Un agent IA qui ouvre une nouvelle session peut charger le contexte complet sans que l'humain ait à tout ré-expliquer.&lt;/p&gt;

&lt;p&gt;C'est l'antidote à la dérive contextuelle : quand les décisions sont documentées dans des artefacts structurés, l'IA peut les respecter session après session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les limites à connaître
&lt;/h3&gt;

&lt;p&gt;Ces approches ne sont pas sans compromis :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overhead documentaire&lt;/strong&gt; : le processus complet BMAD génère des dizaines d'artefacts avant la première ligne de code. Pour un fix rapide, c'est disproportionné (d'où l'existence d'un Quick Flow)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consommation de tokens&lt;/strong&gt; : les allers-retours entre agents consomment significativement plus de tokens qu'un prompt direct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordination manuelle&lt;/strong&gt; : BMAD laisse au développeur la responsabilité de passer les artefacts entre agents, là où Agent Lattice automatise davantage via les skills Kiro&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ce qu'il faut retenir
&lt;/h2&gt;

&lt;p&gt;La méthode BMAD et l'outil Agent Lattice d'AWS représentent une évolution majeure dans l'écosystème AI-DLC : &lt;strong&gt;la structuration de la phase amont&lt;/strong&gt;. Là où la plupart des outils IA se concentrent sur la génération de code, ces frameworks s'attaquent au vrai problème — s'assurer que le code généré respecte une vision produit cohérente et documentée.&lt;/p&gt;

&lt;p&gt;Pour une équipe qui adopte Kiro, la combinaison est naturelle : Agent Lattice pour la phase de Discovery (Design Thinking → specs), puis le workflow natif Kiro (specs → implémentation) pour la phase de Delivery. Le tout versionné dans Git, auditable, et reproductible.&lt;/p&gt;

&lt;p&gt;Le futur du développement assisté par IA n'est pas « l'IA fait tout ». C'est « l'IA exécute un processus structuré, guidé par des artefacts que l'humain valide ». BMAD et Agent Lattice montrent à quoi ce futur ressemble concrètement.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Références :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bmad-code-org/BMAD-METHOD" rel="noopener noreferrer"&gt;BMAD Method — GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aws-samples/sample-e2e-product-development-with-kiro" rel="noopener noreferrer"&gt;Sample E2E Product Development with Kiro — AWS Samples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/pt/blogs/devops/ai-driven-development-life-cycle/" rel="noopener noreferrer"&gt;AI-DLC — AWS DevOps Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jamilxt/bmad-method-vs-ai-dlc-two-ai-development-frameworks-compared-2i28"&gt;BMAD vs AI-DLC — Dev.to&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.augmentcode.com/guides/bmad-method-ai-development" rel="noopener noreferrer"&gt;What Is the BMAD Method — Augment Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
      <category>ia</category>
      <category>architecture</category>
      <category>aws</category>
    </item>
    <item>
      <title>AWS Transit Gateway Policy-Based Routing : le routage intelligent arrive !</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Wed, 19 Aug 2026 08:59:39 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-transit-gateway-policy-based-routing-le-routage-intelligent-arrive--1p1p</link>
      <guid>https://dev.to/aws-builders/aws-transit-gateway-policy-based-routing-le-routage-intelligent-arrive--1p1p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk0xf3c2s5e2pd2u7ik0c.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk0xf3c2s5e2pd2u7ik0c.webp" alt="AWS Transit Gateway Policy-Based Routing" width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Le routage réseau sur AWS a longtemps été contraint par une logique simple : le trafic est acheminé en fonction de l'adresse IP de destination. Point final. Pour les architectes réseau habitués aux fonctionnalités avancées des équipements on-premise (Cisco, Juniper, Palo Alto), cette limitation était frustrante. AWS vient de combler ce gap avec l'annonce de la disponibilité générale du &lt;strong&gt;Policy-Based Routing (PBR)&lt;/strong&gt; sur &lt;a href="https://docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html" rel="noopener noreferrer"&gt;AWS Transit Gateway&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cette fonctionnalité, annoncée le 30 juillet 2026, permet désormais de prendre des décisions de routage basées sur une combinaison d'attributs : adresse IP source, adresse IP destination, ports, et protocole. C'est un changement fondamental dans la manière dont nous concevons les architectures réseau sur AWS.&lt;/p&gt;
&lt;h2&gt;
  
  
  Qu'est-ce que le Policy-Based Routing ?
&lt;/h2&gt;

&lt;p&gt;Le Policy-Based Routing est un mécanisme qui permet de diriger le trafic réseau en fonction de politiques définies par l'administrateur, plutôt que de s'appuyer uniquement sur la table de routage classique basée sur la destination. En d'autres termes, vous pouvez désormais dire : « tout le trafic HTTPS provenant du subnet applicatif à destination du port 443 doit passer par mon appliance d'inspection, tandis que le trafic SSH de l'équipe opérations peut prendre un chemin direct ».&lt;/p&gt;

&lt;p&gt;Sur AWS Transit Gateway, le PBR fonctionne avec un concept de &lt;strong&gt;policy table&lt;/strong&gt; que vous associez à un attachement Transit Gateway. Dans cette table, vous définissez un ensemble ordonné de règles. Chaque règle classifie le trafic selon les critères suivants :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adresse IP source&lt;/strong&gt; : d'où vient le trafic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adresse IP destination&lt;/strong&gt; : où va le trafic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port source et destination&lt;/strong&gt; : quel service est utilisé&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocole&lt;/strong&gt; : TCP, UDP, ICMP, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les règles sont évaluées dans l'ordre avec une logique &lt;strong&gt;first-match-wins&lt;/strong&gt; : la première règle qui correspond au trafic détermine vers quelle route table le paquet sera dirigé. &lt;strong&gt;Si aucune règle ne correspond, le trafic est silencieusement supprimé (implicit deny)&lt;/strong&gt;. Ce comportement, similaire à celui des Security Groups, impose de toujours prévoir une règle catch-all si vous souhaitez éviter les drops involontaires.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pourquoi c'est un game-changer ?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Avant le PBR : la complexité architecturale
&lt;/h3&gt;

&lt;p&gt;Avant cette annonce, les architectes réseau qui avaient besoin de diriger le trafic de manière granulaire devaient construire des architectures multi-VPC complexes avec des sauts de routage supplémentaires. Concrètement, cela signifiait :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiplier les VPC d'inspection&lt;/strong&gt; : un VPC dédié pour chaque type de trafic à inspecter différemment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ajouter des Gateway Load Balancers&lt;/strong&gt; : pour distribuer le trafic vers des appliances tierces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Créer des chaînes de routage&lt;/strong&gt; : avec plusieurs Transit Gateway route tables interconnectées&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gérer des coûts croissants&lt;/strong&gt; : chaque saut supplémentaire génère des frais de traitement de données&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette complexité se traduisait par une surcharge opérationnelle importante, des latences accrues, et un risque d'erreur de configuration élevé.&lt;/p&gt;
&lt;h3&gt;
  
  
  Avec le PBR : la simplicité retrouvée
&lt;/h3&gt;

&lt;p&gt;Le PBR élimine une grande partie de cette complexité en étendant les capacités natives de routage du Transit Gateway. Plus besoin d'ajouter des couches intermédiaires : vous classifiez et dirigez le trafic directement au niveau du Transit Gateway, en une seule étape.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cas d'usage concrets
&lt;/h2&gt;

&lt;p&gt;Le PBR ouvre la porte à de nombreux scénarios que les équipes réseau et sécurité attendaient depuis longtemps.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inspection sélective du trafic
&lt;/h3&gt;

&lt;p&gt;C'est probablement le cas d'usage le plus demandé. Plutôt que de faire passer tout le trafic par &lt;a href="https://docs.aws.amazon.com/network-firewall/latest/developerguide/what-is-aws-network-firewall.html" rel="noopener noreferrer"&gt;AWS Network Firewall&lt;/a&gt; ou une appliance tierce (ce qui génère des coûts et de la latence), vous pouvez désormais ne router que le trafic sensible vers l'inspection. Par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le trafic à destination des bases de données (port 3306, 5432) passe par l'inspection&lt;/li&gt;
&lt;li&gt;Le trafic interne entre microservices sur des ports applicatifs connus peut contourner l'inspection&lt;/li&gt;
&lt;li&gt;Le trafic vers des destinations externes spécifiques est systématiquement inspecté&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Routage basé sur la source pour la connectivité hybride
&lt;/h3&gt;

&lt;p&gt;Pour les entreprises utilisant &lt;a href="https://docs.aws.amazon.com/directconnect/latest/UserGuide/Welcome.html" rel="noopener noreferrer"&gt;AWS Direct Connect&lt;/a&gt; et &lt;a href="https://docs.aws.amazon.com/vpn/latest/s2svpn/VPC_VPN.html" rel="noopener noreferrer"&gt;AWS VPN&lt;/a&gt; en parallèle, le PBR permet de diriger le trafic vers le bon chemin en fonction de sa source ou de son protocole :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le trafic critique (bases de données, ERP) emprunte le Direct Connect pour bénéficier de la latence faible et de la bande passante garantie&lt;/li&gt;
&lt;li&gt;Le trafic moins sensible (mises à jour, synchronisation) peut utiliser le VPN comme chemin secondaire&lt;/li&gt;
&lt;li&gt;Le basculement peut être géré de manière plus fine en fonction des applications&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Isolation des environnements
&lt;/h3&gt;

&lt;p&gt;Le PBR permet d'isoler les environnements de production et de développement dans des domaines de routage séparés, limitant ainsi les mouvements latéraux. Même si deux environnements partagent des plages IP similaires ou des attachements communs, les règles PBR garantissent que le trafic de développement ne peut jamais atteindre les ressources de production, et inversement.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration et mise en place
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Contrainte fondamentale : policy table OU route table, jamais les deux
&lt;/h3&gt;

&lt;p&gt;C'est le point le plus important à comprendre avant de se lancer : &lt;strong&gt;un attachement Transit Gateway ne peut être associé qu'à une policy table OU à une route table, jamais aux deux simultanément&lt;/strong&gt;. Il n'existe aucun mode hybride. Concrètement :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si votre attachement VPC est actuellement associé à une route table classique, vous &lt;strong&gt;devez d'abord dissocier&lt;/strong&gt; cette route table avant de pouvoir associer une policy table&lt;/li&gt;
&lt;li&gt;Pendant la fenêtre de dissociation/association, &lt;strong&gt;le trafic de cet attachement sera interrompu&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Une policy table vide (sans aucune règle) entraîne le &lt;strong&gt;drop de tout le trafic entrant&lt;/strong&gt; sur cet attachement — c'est l'implicit deny&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette exclusivité signifie que le PBR remplace complètement la logique de routage classique pour un attachement donné. C'est un choix architectural binaire par attachement.&lt;/p&gt;
&lt;h3&gt;
  
  
  Les étapes de mise en place
&lt;/h3&gt;

&lt;p&gt;La configuration du PBR se fait en quatre étapes :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Créer les route tables cibles&lt;/strong&gt; : chaque règle PBR pointe vers une route table TGW qui contient les routes effectives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Créer une policy table&lt;/strong&gt; : vous définissez une table de politiques associée à votre Transit Gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Définir les règles&lt;/strong&gt; : vous créez un ensemble ordonné de règles (numérotées de 1 à 50 000) avec les critères de classification et la route table cible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dissocier la route table existante puis associer la policy table à l'attachement&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le PBR est configurable via la &lt;a href="https://console.aws.amazon.com/" rel="noopener noreferrer"&gt;Console AWS&lt;/a&gt;, l'&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ec2/" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt;, et les &lt;a href="https://docs.aws.amazon.com/sdkref/latest/guide/overview.html" rel="noopener noreferrer"&gt;SDK AWS&lt;/a&gt;. Les commandes CLI dédiées (&lt;code&gt;create-transit-gateway-policy-table&lt;/code&gt;, &lt;code&gt;create-transit-gateway-policy-table-entry&lt;/code&gt;, &lt;code&gt;associate-transit-gateway-policy-table&lt;/code&gt;) sont disponibles dès maintenant.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exemple concret : filtrage HTTP/HTTPS et SSH
&lt;/h3&gt;

&lt;p&gt;Voici un exemple complet de mise en place via AWS CLI, qui implémente le scénario décrit en introduction : le trafic HTTPS est inspecté, le trafic SSH prend un chemin direct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Créer la policy table&lt;/span&gt;
aws ec2 create-transit-gateway-policy-table &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-id&lt;/span&gt; tgw-0bc994abffEXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=transit-gateway-policy-table,Tags=[{Key=Name,Value=app-security-policy}]'&lt;/span&gt;
&lt;span class="c"&gt;# Retourne : tgw-ptb-0ca78a549EXAMPLE&lt;/span&gt;

&lt;span class="c"&gt;# 2. Règle 100 : trafic HTTPS (port 443) du subnet applicatif → inspection firewall&lt;/span&gt;
aws ec2 create-transit-gateway-policy-table-entry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule-number&lt;/span&gt; 100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule&lt;/span&gt; &lt;span class="s1"&gt;'{"SourceCidrBlock":"10.1.10.0/24","Protocol":"6","DestinationPortRange":"443"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-route-table-id&lt;/span&gt; tgw-rtb-0a823edbdeEXAMPLE

&lt;span class="c"&gt;# 3. Règle 200 : trafic HTTP (port 80) → même inspection&lt;/span&gt;
aws ec2 create-transit-gateway-policy-table-entry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule-number&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule&lt;/span&gt; &lt;span class="s1"&gt;'{"SourceCidrBlock":"10.1.10.0/24","Protocol":"6","DestinationPortRange":"80"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-route-table-id&lt;/span&gt; tgw-rtb-0a823edbdeEXAMPLE

&lt;span class="c"&gt;# 4. Règle 300 : trafic SSH (port 22) de l'équipe ops → routage direct (pas d'inspection)&lt;/span&gt;
&lt;span class="c"&gt;#    Ne matche que si ce trafic entre bien par l'attachement associé à la policy table&lt;/span&gt;
aws ec2 create-transit-gateway-policy-table-entry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule-number&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule&lt;/span&gt; &lt;span class="s1"&gt;'{"SourceCidrBlock":"10.1.50.0/24","Protocol":"6","DestinationPortRange":"22"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-route-table-id&lt;/span&gt; tgw-rtb-0b91f2c3d4EXAMPLE

&lt;span class="c"&gt;# 5. Règle 40000 : catch-all → routage par défaut (évite l'implicit deny)&lt;/span&gt;
&lt;span class="c"&gt;#    Un policy-rule vide matche tout : toutes les conditions valent * par défaut&lt;/span&gt;
aws ec2 create-transit-gateway-policy-table-entry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule-number&lt;/span&gt; 40000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-rule&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-route-table-id&lt;/span&gt; tgw-rtb-0f5e4d3c2bEXAMPLE

&lt;span class="c"&gt;# 6. Vérifier les entries avant de basculer l'attachement&lt;/span&gt;
aws ec2 get-transit-gateway-policy-table-entries &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE

&lt;span class="c"&gt;# 7. Dissocier la route table existante de l'attachement source&lt;/span&gt;
&lt;span class="c"&gt;#    Un attachement ne peut être associé qu'à une route table OU une policy table&lt;/span&gt;
aws ec2 disassociate-transit-gateway-route-table &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-attachment-id&lt;/span&gt; tgw-attach-0def6EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-route-table-id&lt;/span&gt; tgw-rtb-0c7d8e9f01EXAMPLE

&lt;span class="c"&gt;# 8. Attendre la fin de la dissociation : associer trop tôt fait échouer la requête&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; :&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;STATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws ec2 get-transit-gateway-route-table-associations &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--transit-gateway-route-table-id&lt;/span&gt; tgw-rtb-0c7d8e9f01EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=transit-gateway-attachment-id,Values=tgw-attach-0def6EXAMPLE"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Associations[0].State'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="c"&gt;# "None" : l'association a disparu de la liste&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"None"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"disassociated"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;break
  &lt;/span&gt;&lt;span class="k"&gt;fi
  &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;5
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c"&gt;# 9. Associer la policy table à l'attachement&lt;/span&gt;
aws ec2 associate-transit-gateway-policy-table &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-attachment-id&lt;/span&gt; tgw-attach-0def6EXAMPLE

&lt;span class="c"&gt;# 10. Confirmer l'association&lt;/span&gt;
aws ec2 get-transit-gateway-policy-table-associations &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--transit-gateway-policy-table-id&lt;/span&gt; tgw-ptb-0ca78a549EXAMPLE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avec cette configuration, le trafic est traité comme suit :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paquet TCP:443 depuis &lt;code&gt;10.1.10.x&lt;/code&gt; → &lt;strong&gt;inspecté par le firewall&lt;/strong&gt; (règle 100)&lt;/li&gt;
&lt;li&gt;Paquet TCP:80 depuis &lt;code&gt;10.1.10.x&lt;/code&gt; → &lt;strong&gt;inspecté par le firewall&lt;/strong&gt; (règle 200)&lt;/li&gt;
&lt;li&gt;Paquet TCP:22 depuis &lt;code&gt;10.1.50.x&lt;/code&gt; → &lt;strong&gt;routage direct&lt;/strong&gt; sans inspection (règle 300)&lt;/li&gt;
&lt;li&gt;Tout autre trafic → &lt;strong&gt;routage par défaut&lt;/strong&gt; (règle 40000 catch-all)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Considérations et bonnes pratiques
&lt;/h2&gt;

&lt;p&gt;Comme toute fonctionnalité réseau avancée, le PBR nécessite une approche structurée :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commencez simple&lt;/strong&gt; : déployez d'abord une ou deux règles sur un attachement non-critique pour valider le comportement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentez vos politiques&lt;/strong&gt; : la logique first-match-wins peut devenir complexe avec de nombreuses règles. Maintenez une documentation claire de l'ordre et de l'intention de chaque règle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surveillez les métriques&lt;/strong&gt; : utilisez &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt; pour monitorer les hits sur chaque règle et identifier les règles inutilisées. La métrique &lt;code&gt;PacketDropCountNoPolicy&lt;/code&gt; vous alerte quand du trafic est droppé faute de règle correspondante&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prévoyez toujours une règle catch-all&lt;/strong&gt; : sauf si vous souhaitez explicitement un comportement Zero Trust (deny-all), ajoutez une règle à numéro élevé (ex: 40000) qui capture le trafic restant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laissez des gaps entre les numéros de règle&lt;/strong&gt; : utilisez 100, 200, 300… pour pouvoir insérer de nouvelles règles sans tout renuméroter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testez les scénarios de basculement&lt;/strong&gt; : validez que vos règles PBR se comportent correctement en cas de panne d'un attachement cible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attention au BGP&lt;/strong&gt; : associer une policy table à un attachement VPN (Site-to-Site) ou Connect &lt;strong&gt;stoppe les advertisements BGP&lt;/strong&gt; vers le peer. Direct Connect n'est pas affecté (utilise la liste allowed-prefixes)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Impact sur la latence réseau
&lt;/h2&gt;

&lt;p&gt;Une question légitime : le PBR ajoute-t-il de la latence au transit du trafic ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La réponse est non.&lt;/strong&gt; L'évaluation des règles PBR s'effectue au niveau du plan de données du Transit Gateway, au même point de décision que la table de routage classique. Il n'y a pas de saut réseau supplémentaire, pas de composant intermédiaire ajouté dans le chemin. La décision est prise « en ligne » lors du transit du paquet.&lt;/p&gt;

&lt;p&gt;En réalité, le PBR peut même &lt;strong&gt;réduire la latence globale&lt;/strong&gt; de votre architecture :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avant le PBR&lt;/strong&gt; : pour inspecter sélectivement le trafic, il fallait tout envoyer vers un VPC d'inspection (un saut supplémentaire) puis filtrer au niveau de l'appliance. Même le trafic « propre » subissait la traversée.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avec le PBR&lt;/strong&gt; : seul le trafic qui nécessite effectivement une inspection est dirigé vers l'appliance. Le reste prend le chemin direct, économisant un ou plusieurs sauts réseau.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les quotas de bande passante ne sont pas impactés non plus : chaque attachement VPC conserve sa capacité de 100 Gbps par Availability Zone dans chaque direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limites et quotas
&lt;/h2&gt;

&lt;p&gt;Comme tout service AWS, le PBR a ses limites qu'il faut connaître avant de concevoir votre architecture :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ressource&lt;/th&gt;
&lt;th&gt;Limite&lt;/th&gt;
&lt;th&gt;Ajustable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Policy tables par Transit Gateway&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policy entries (customer-managed) par TGW, toutes tables confondues&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Numéros de règle&lt;/td&gt;
&lt;td&gt;1 à 50 000&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Types d'attachement supportés&lt;/td&gt;
&lt;td&gt;VPC, VPN, Direct Connect, Connect, Peering (sauf Cloud WAN)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Autres contraintes importantes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exclusivité absolue&lt;/strong&gt; : un attachement est associé à une policy table OU une route table, jamais les deux&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pas de PBR sur les peering Cloud WAN&lt;/strong&gt; : seules les entries system-managed (gérées par Cloud WAN) s'appliquent sur ces attachements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ports limités à TCP/UDP&lt;/strong&gt; : le filtrage par port ne fonctionne que pour les protocoles TCP (6) et UDP (17). Pour ICMP, GRE ou « Any », les ports sont automatiquement à &lt;code&gt;*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy table vide = blackhole&lt;/strong&gt; : associer une policy table sans aucune règle à un attachement provoque le drop silencieux de tout le trafic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route table référencée non supprimable&lt;/strong&gt; : une route table utilisée comme cible par une policy entry ne peut pas être supprimée tant que la référence existe&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migration : passer d'une route table au PBR sans coupure
&lt;/h2&gt;

&lt;p&gt;La migration vers le PBR est la question qui préoccupe le plus les équipes réseau en production. Soyons clairs : &lt;strong&gt;il existe une micro-interruption inévitable&lt;/strong&gt; lors du basculement, car la dissociation de la route table et l'association de la policy table ne sont pas atomiques.&lt;/p&gt;

&lt;p&gt;Voici la stratégie recommandée pour minimiser l'impact :&lt;/p&gt;

&lt;h3&gt;
  
  
  Approche progressive (recommandée)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Préparez tout en amont&lt;/strong&gt; : créez la policy table, définissez toutes les règles, et créez les route tables cibles avec les routes nécessaires — tout cela sans aucun impact sur le trafic existant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commencez par un attachement non-critique&lt;/strong&gt; : choisissez un VPC de développement ou de test pour valider le comportement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incluez une règle catch-all qui réplique le comportement actuel&lt;/strong&gt; : votre règle à numéro élevé doit pointer vers une route table qui reproduit exactement le routage actuel. Ainsi, même si vos règles spécifiques ont un bug, le trafic continue de transiter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planifiez une fenêtre de maintenance&lt;/strong&gt; : la dissociation de la route table suivie de l'association de la policy table prend généralement quelques secondes, mais prévoyez 30 à 60 secondes de micro-coupure potentielle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basculez&lt;/strong&gt; : dissociez la route table, puis associez immédiatement la policy table&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validez&lt;/strong&gt; : vérifiez les flux avec &lt;code&gt;GetTransitGatewayPolicyTableEntries&lt;/code&gt; et surveillez la métrique &lt;code&gt;PacketDropCountNoPolicy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Itérez&lt;/strong&gt; : une fois validé, répétez sur les attachements de production&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Ce qui se passe pendant la bascule
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Route table associée] ──dissociation──▶ [Aucune association] ──association──▶ [Policy table associée]
                                              │
                                    Trafic droppé pendant
                                    cette fenêtre (secondes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pendant la fenêtre où l'attachement n'a ni route table ni policy table, &lt;strong&gt;le trafic entrant est droppé&lt;/strong&gt;. Les connexions TCP établies seront coupées et devront être ré-établies. Pour les protocoles stateless (UDP, ICMP), la reprise est transparente dès que la policy table est active.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stratégies de mitigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Applications tolérantes&lt;/strong&gt; : la plupart des applications avec des mécanismes de retry (HTTP, gRPC) survivent à une interruption de quelques secondes sans impact utilisateur visible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trafic critique&lt;/strong&gt; : pour les flux qui ne tolèrent aucune perte, envisagez un schéma de migration par duplication d'attachement — créez un second attachement VPC (dans un subnet dédié), migrez-le vers PBR, puis basculez le trafic applicatif vers ce nouveau subnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS failover&lt;/strong&gt; : si vous avez un mécanisme de failover DNS (Route 53 health checks), vous pouvez basculer le trafic temporairement vers un chemin alternatif le temps de la migration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coordination multi-AZ&lt;/strong&gt; : migrez un AZ à la fois si votre architecture le permet (attachements distincts par AZ)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rollback
&lt;/h3&gt;

&lt;p&gt;En cas de problème, le rollback est simple : dissociez la policy table et réassociez l'ancienne route table. La même micro-interruption s'applique dans l'autre sens. C'est pourquoi il est essentiel de &lt;strong&gt;ne pas supprimer l'ancienne route table&lt;/strong&gt; tant que la migration n'est pas validée en production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disponibilité et tarification
&lt;/h2&gt;

&lt;p&gt;Le Policy-Based Routing pour AWS Transit Gateway est disponible dans toutes les régions commerciales AWS où Transit Gateway est disponible. Point important : &lt;strong&gt;le PBR n'engendre aucun coût supplémentaire&lt;/strong&gt; au-delà des frais standard de Transit Gateway (frais par attachement + frais de traitement de données). Il n'y a pas de tarification par règle ni par évaluation. C'est une excellente nouvelle car cela signifie que l'adoption ne sera pas freinée par des considérations budgétaires.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Pour les architectes réseau et les équipes sécurité, c'est une fonctionnalité qui va simplifier considérablement les architectures existantes tout en ouvrant de nouvelles possibilités.&lt;/p&gt;

&lt;p&gt;Mon conseil : si vous avez aujourd'hui des architectures multi-VPC complexes uniquement pour gérer du routage conditionnel, c'est le moment de revoir votre design. Le PBR peut potentiellement vous permettre de réduire le nombre de composants intermédiaires, diminuer la latence, et simplifier vos opérations quotidiennes.&lt;/p&gt;

&lt;p&gt;Commencez par identifier vos flux de trafic les plus critiques qui nécessitent un traitement différencié, puis testez le PBR sur un périmètre restreint avant de l'étendre à l'ensemble de votre organisation.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>reseau</category>
      <category>architecture</category>
    </item>
    <item>
      <title>AWS Lambda MicroVMs : bastions serverless, sandboxes IA et Cloud9 DIY avec VS Code OSS + EFS</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:12:49 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-lambda-microvms-bastions-serverless-sandboxes-ia-et-cloud9-diy-avec-vs-code-oss-efs-3pa7</link>
      <guid>https://dev.to/aws-builders/aws-lambda-microvms-bastions-serverless-sandboxes-ia-et-cloud9-diy-avec-vs-code-oss-efs-3pa7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcbxcjzp45bmrlhioa5gb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcbxcjzp45bmrlhioa5gb.webp" alt="AWS Lambda MicroVMs" width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Le 22 juin 2026, AWS a lancé &lt;strong&gt;Lambda MicroVMs&lt;/strong&gt;, un nouveau type de ressource serverless qui change la donne. Jusqu'ici, Lambda était synonyme de fonctions stateless limitées à 15 minutes. Désormais, vous pouvez obtenir une &lt;strong&gt;machine virtuelle Firecracker dédiée&lt;/strong&gt;, stateful, avec isolation hardware, démarrage quasi-instantané depuis un snapshot, et une durée de vie allant jusqu'à &lt;strong&gt;8 heures&lt;/strong&gt;. Le tout sans infrastructure à gérer.&lt;/p&gt;

&lt;p&gt;Ce n'est pas une évolution incrémentale de Lambda Functions — c'est un nouveau type de ressource avec sa propre API (&lt;code&gt;run-microvm&lt;/code&gt;, &lt;code&gt;suspend-microvm&lt;/code&gt;, &lt;code&gt;resume-microvm&lt;/code&gt;). AWS expose directement la couche Firecracker qui propulsait déjà secrètement plus de 15 000 milliards d'invocations Lambda par mois.&lt;/p&gt;

&lt;p&gt;Dans cet article, nous allons explorer ce que Lambda MicroVMs apporte concrètement, pourquoi c'est un game-changer pour les bastions et les sandboxes, puis nous construirons pas à pas un &lt;strong&gt;équivalent de Cloud9&lt;/strong&gt; basé sur OpenVSCode Server, Lambda MicroVM et Amazon EFS pour la persistance du code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lambda MicroVMs : ce que c'est (et ce que ce n'est pas)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Architecture et spécifications
&lt;/h3&gt;

&lt;p&gt;Lambda MicroVMs repose sur le modèle &lt;strong&gt;image-then-launch&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vous fournissez un Dockerfile + code source packagé en zip sur S3&lt;/li&gt;
&lt;li&gt;Lambda exécute le Dockerfile, lance votre application via &lt;code&gt;ENTRYPOINT&lt;/code&gt; ou &lt;code&gt;CMD&lt;/code&gt;, attend le signal &lt;code&gt;/ready&lt;/code&gt; (hook optionnel), puis capture un &lt;strong&gt;snapshot Firecracker&lt;/strong&gt; (mémoire + disque)&lt;/li&gt;
&lt;li&gt;Chaque lancement ultérieur reprend depuis ce snapshot pré-initialisé — démarrage quasi-instantané&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Le sizing suit un modèle &lt;strong&gt;baseline-peak&lt;/strong&gt; : vous configurez une baseline, et la MicroVM peut burst jusqu'à &lt;strong&gt;4x&lt;/strong&gt; cette baseline automatiquement. Vous payez la baseline tant que la MicroVM tourne, et uniquement le surplus consommé au-delà.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Baseline&lt;/th&gt;
&lt;th&gt;Peak (burst 4x)&lt;/th&gt;
&lt;th&gt;Disque max&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0,5 Go / 0,25 vCPU&lt;/td&gt;
&lt;td&gt;2 Go / 1 vCPU&lt;/td&gt;
&lt;td&gt;8 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 Go / 0,5 vCPU&lt;/td&gt;
&lt;td&gt;4 Go / 2 vCPU&lt;/td&gt;
&lt;td&gt;8 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;2 Go / 1 vCPU&lt;/strong&gt; (défaut)&lt;/td&gt;
&lt;td&gt;8 Go / 4 vCPU&lt;/td&gt;
&lt;td&gt;8 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 Go / 2 vCPU&lt;/td&gt;
&lt;td&gt;16 Go / 8 vCPU&lt;/td&gt;
&lt;td&gt;16 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 Go / 4 vCPU&lt;/td&gt;
&lt;td&gt;32 Go / 16 vCPU&lt;/td&gt;
&lt;td&gt;32 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Autres caractéristiques :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Caractéristique&lt;/th&gt;
&lt;th&gt;Valeur&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Architecture&lt;/td&gt;
&lt;td&gt;ARM64 (Graviton) uniquement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Durée max&lt;/td&gt;
&lt;td&gt;8 heures (28 800 secondes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isolation&lt;/td&gt;
&lt;td&gt;Firecracker microVM — kernel dédié, pas de partage entre sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;Amazon Linux 2023 (base image managée par Lambda)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocoles inbound&lt;/td&gt;
&lt;td&gt;HTTP/1.1, HTTP/2, WebSockets, gRPC, SSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentification&lt;/td&gt;
&lt;td&gt;Token JWE obligatoire (&lt;code&gt;X-aws-proxy-auth&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Ce qui différencie Lambda MicroVMs
&lt;/h3&gt;

&lt;p&gt;Le positionnement est clair : Lambda MicroVMs se situe &lt;strong&gt;entre&lt;/strong&gt; Lambda Functions et EC2 :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lambda Functions&lt;/strong&gt; : stateless, 15 min max, event-driven, scale-to-zero&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda MicroVMs&lt;/strong&gt; : stateful, 8h max, interactive, suspend/resume avec état intact&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2&lt;/strong&gt; : stateful, illimité, mais vous gérez tout (AMI, scaling, patching...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le modèle économique est intéressant : 0\$ de compute pendant la suspension. Vous payez uniquement le stockage du snapshot (~0,08\$/Go/mois) et les opérations de suspend/resume. Pour des workloads qui utilisent beaucoup le burst (exactement le profil d'un développeur ou d'un agent IA), c'est redoutable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cas d'usage : bastions et sandboxes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Bastions éphémères serverless
&lt;/h3&gt;

&lt;p&gt;Traditionnellement, un bastion SSH est une instance EC2 t3.micro qui tourne 24/7 dans un subnet public ou privé, avec un coût fixe mensuel et une surface d'attaque permanente. Avec Lambda MicroVMs, vous pouvez repenser complètement cette approche :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Le concept&lt;/strong&gt; : un bastion qui n'existe que quand vous en avez besoin, avec isolation VM complète, et qui disparaît après usage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Créer un network connector VPC pour le bastion (une seule fois)&lt;/span&gt;
aws lambda-core create-network-connector &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; bastion-vpc-egress &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
    "VpcEgressConfiguration": {
      "SubnetIds": ["subnet-private-a"],
      "SecurityGroupIds": ["sg-bastion"],
      "NetworkProtocol": "IPv4",
      "AssociatedComputeResourceTypes": ["MicroVm"]
    }
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--operator-role&lt;/span&gt; arn:aws:iam::123456789012:role/NetworkConnectorOperatorRole

&lt;span class="c"&gt;# Lancer un bastion éphémère&lt;/span&gt;
aws lambda-microvms run-microvm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image-identifier&lt;/span&gt; arn:aws:lambda:eu-west-1:123456789012:microvm-image:bastion-hardened &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--execution-role-arn&lt;/span&gt; arn:aws:iam::123456789012:role/BastionMicroVMRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ingress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--egress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:123456789012:network-connector:bastion-vpc-egress"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--idle-policy&lt;/span&gt; &lt;span class="s1"&gt;'{"maxIdleDurationSeconds":1800,"suspendedDurationSeconds":600,"autoResumeEnabled":false}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Avantages par rapport à un bastion EC2 classique&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coût quasi-nul&lt;/strong&gt; : le bastion est suspendu (gratuit en compute) quand personne ne l'utilise. Fini le t3.micro qui tourne 730h/mois pour 10h d'utilisation effective&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surface d'attaque réduite&lt;/strong&gt; : pas de machine permanente exposée, kernel dédié sans partage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immutabilité&lt;/strong&gt; : chaque session repart d'un snapshot propre. Pas de drift de configuration, pas de malware persistant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit natif&lt;/strong&gt; : chaque &lt;code&gt;run-microvm&lt;/code&gt; est un événement CloudTrail. Qui a lancé quoi, quand, combien de temps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-destruction&lt;/strong&gt; : politique d'idle qui termine automatiquement le bastion après inactivité&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le bastion MicroVM est particulièrement pertinent pour les équipes qui pratiquent le &lt;strong&gt;Just-In-Time access&lt;/strong&gt; : un SRE déclenche un bastion via une Step Function, obtient un accès temporaire à un RDS ou un cluster EKS, et le bastion est terminé 30 minutes plus tard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sandboxes pour agents IA et exécution de code non fiable
&lt;/h3&gt;

&lt;p&gt;C'est le cas d'usage principal mis en avant par AWS. Les agents IA (coding assistants, data analysts, vulnerability scanners) ont besoin d'exécuter du code qu'ils génèrent eux-mêmes dans un environnement isolé. Lambda MicroVMs résout le trilemme classique :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt; : démarrage rapide mais isolation faible (kernel partagé)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VMs EC2&lt;/strong&gt; : isolation forte mais démarrage lent et gestion lourde&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda MicroVMs&lt;/strong&gt; : isolation hardware + démarrage rapide + zéro gestion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS a d'ailleurs publié une &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/microvms-integrations-claude-managed-agents.html" rel="noopener noreferrer"&gt;intégration native avec Claude Managed Agents&lt;/a&gt; : chaque appel d'outil de l'agent s'exécute dans une MicroVM dédiée, isolée du reste du système.&lt;/p&gt;

&lt;p&gt;Pour les plateformes SaaS multi-tenant, c'est le pattern idéal : un étudiant qui exécute du Python sur votre plateforme éducative ne peut jamais accéder aux données d'un autre étudiant, car chaque session tourne dans son propre kernel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutoriel : recréer Cloud9 avec Lambda MicroVM + VS Code OSS + EFS
&lt;/h2&gt;

&lt;p&gt;AWS a retiré Cloud9 des offres pour les nouveaux comptes. Voici comment construire un &lt;strong&gt;environnement de développement cloud serverless&lt;/strong&gt; qui le remplace en combinant Lambda MicroVM, OpenVSCode Server et Amazon EFS pour la persistance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture cible
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                    Développeur (navigateur)             │
│         https://mvm-xxx.lambda-microvm.eu-west-1.on.aws│
│         Header: X-aws-proxy-auth: &amp;lt;token&amp;gt;              │
└──────────────────────────────┬──────────────────────────┘
                               │ HTTPS (port 8080)
                               ▼
┌─────────────────────────────────────────────────────────┐
│              Lambda MicroVM (ARM64 / Graviton)          │
│              Baseline: 4 Go / 2 vCPU                   │
│              Peak: 16 Go / 8 vCPU (burst auto)         │
│                                                         │
│  ┌─────────────────────────────────────────────────┐    │
│  │         OpenVSCode Server (port 8080)           │    │
│  │         Extensions, terminal, LSP               │    │
│  └─────────────────────────────────────────────────┘    │
│                                                         │
│  ┌─────────────────────────────────────────────────┐    │
│  │         /home/developer/workspace               │    │
│  │         (local ou mount EFS optionnel)          │    │
│  └─────────────────────────────────────────────────┘    │
│                                                         │
│  Runtime: Node.js 20, Python 3.12, AWS CLI v2           │
└─────────────────────────────────────────────────────────┘
                               │ (optionnel) NFS via VPC
                               ▼            egress connector
┌─────────────────────────────────────────────────────────┐
│              Amazon EFS (Access Point /dev/workspace)   │
│              Persistance du code entre sessions         │
│              Throughput mode: elastic                   │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Étape 1 : créer le filesystem EFS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Créer le filesystem&lt;/span&gt;
aws efs create-file-system &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--performance-mode&lt;/span&gt; generalPurpose &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--throughput-mode&lt;/span&gt; elastic &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--encrypted&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tags&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Name,Value&lt;span class="o"&gt;=&lt;/span&gt;dev-workspace-efs &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1

&lt;span class="c"&gt;# Créer un Access Point dédié&lt;/span&gt;
aws efs create-access-point &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--file-system-id&lt;/span&gt; fs-0abc123def456 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--posix-user&lt;/span&gt; &lt;span class="nv"&gt;Uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000,Gid&lt;span class="o"&gt;=&lt;/span&gt;1000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--root-directory&lt;/span&gt; &lt;span class="s2"&gt;"Path=/dev/workspace,CreationInfo={OwnerUid=1000,OwnerGid=1000,Permissions=755}"&lt;/span&gt;

&lt;span class="c"&gt;# Créer les mount targets dans les subnets privés&lt;/span&gt;
aws efs create-mount-target &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--file-system-id&lt;/span&gt; fs-0abc123def456 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; subnet-private-a &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--security-groups&lt;/span&gt; sg-efs-access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Étape 2 : construire l'image MicroVM
&lt;/h3&gt;

&lt;p&gt;Voici le Dockerfile qui crée notre environnement de développement. On utilise l'image de base container &lt;code&gt;public.ecr.aws/lambda/microvms:al2023-minimal&lt;/code&gt; fournie par AWS, qui est compatible avec le processus de snapshot Firecracker :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; public.ecr.aws/lambda/microvms:al2023-minimal&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; root&lt;/span&gt;

&lt;span class="c"&gt;# Outils système de base&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nodejs20 npm &lt;span class="se"&gt;\
&lt;/span&gt;    python3.12 python3.12-pip &lt;span class="se"&gt;\
&lt;/span&gt;    git wget unzip &lt;span class="nb"&gt;tar gzip&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; dnf clean all

&lt;span class="c"&gt;# AWS CLI v2&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; unzip awscliv2.zip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./aws/install &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; aws awscliv2.zip

&lt;span class="c"&gt;# OpenVSCode Server (build ARM64)&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; OPENVSCODE_VERSION=1.109.5&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /opt/vscode &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/gitpod-io/openvscode-server/releases/download/openvscode-server-v&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENVSCODE_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/openvscode-server-v&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENVSCODE_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-linux-arm64.tar.gz"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    | &lt;span class="nb"&gt;tar &lt;/span&gt;xz &lt;span class="nt"&gt;--strip-components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-C&lt;/span&gt; /opt/vscode

&lt;span class="c"&gt;# Créer l'utilisateur développeur avec workspace local&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; 1000 &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash developer &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/developer/workspace &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/developer/.openvscode-server/data/Machine &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; developer:developer /home/developer

&lt;span class="c"&gt;# Pré-configurer pour désactiver le workspace trust (évite le reload loop)&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"security.workspace.trust.enabled": false}'&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/developer/.openvscode-server/data/Machine/settings.json &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown &lt;/span&gt;developer:developer /home/developer/.openvscode-server/data/Machine/settings.json

&lt;span class="c"&gt;# Script d'entrypoint&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; entrypoint.sh /opt/entrypoint.sh&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /opt/entrypoint.sh

&lt;span class="c"&gt;# Extensions VS Code pré-installées&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;su - developer &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"/opt/vscode/bin/openvscode-server &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    --install-extension ms-python.python &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    --install-extension dbaeumer.vscode-eslint &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    --install-extension esbenp.prettier-vscode &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    --install-extension amazonwebservices.aws-toolkit-vscode"&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/developer/workspace&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/opt/entrypoint.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quelques points importants sur ce Dockerfile :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;USER root&lt;/code&gt;&lt;/strong&gt; : nécessaire pour installer les paquets système et créer l'utilisateur. L'entrypoint switchera vers &lt;code&gt;developer&lt;/code&gt; pour lancer VS Code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;OPENVSCODE_VERSION=1.109.5&lt;/code&gt;&lt;/strong&gt; : version ARM64 stable de &lt;a href="https://github.com/gitpod-io/openvscode-server" rel="noopener noreferrer"&gt;OpenVSCode Server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace trust désactivé&lt;/strong&gt; : sans cette configuration, OpenVSCode Server entre dans un reload loop au premier accès car il demande à l'utilisateur de « faire confiance » au workspace&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensions pré-installées&lt;/strong&gt; : elles sont incluses dans le snapshot, donc disponibles instantanément au démarrage sans téléchargement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Étape 3 : le script d'entrypoint
&lt;/h3&gt;

&lt;p&gt;L'entrypoint lance OpenVSCode Server en tant qu'utilisateur &lt;code&gt;developer&lt;/code&gt;. Le montage EFS est géré au niveau de la MicroVM via le VPC egress connector — la MicroVM accède à EFS par le réseau NFS depuis le subnet privé configuré.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# entrypoint.sh — Lance OpenVSCode Server&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Lancer OpenVSCode Server en tant que developer&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;su - developer &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"/opt/vscode/bin/openvscode-server &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --host 0.0.0.0 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --port 8080 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --without-connection-token &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --default-folder /home/developer/workspace"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note sur EFS&lt;/strong&gt; : le Dockerfile fourni ne contient pas &lt;code&gt;nfs-utils&lt;/code&gt; et ne monte pas EFS dans l'entrypoint. Pour ajouter la persistance EFS, deux options :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Montage NFS dans l'entrypoint&lt;/strong&gt; : ajouter &lt;code&gt;nfs-utils&lt;/code&gt; au Dockerfile, activer &lt;code&gt;--additional-os-capabilities '["ALL"]'&lt;/code&gt; lors du &lt;code&gt;create-microvm-image&lt;/code&gt; (nécessaire pour &lt;code&gt;mount&lt;/code&gt;), et monter EFS avant de lancer VS Code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace local&lt;/strong&gt; : utiliser &lt;code&gt;/home/developer/workspace&lt;/code&gt; comme stockage éphémère — le code est perdu à la terminaison mais conservé pendant suspend/resume (le snapshot préserve l'état disque)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;L'option 1 avec montage EFS dans l'entrypoint ressemblerait à :&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# entrypoint.sh — Version avec montage EFS&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nv"&gt;EFS_DNS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EFS_FILE_SYSTEM_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.efs.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.amazonaws.com"&lt;/span&gt;
&lt;span class="nv"&gt;MOUNT_POINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/home/developer/workspace"&lt;/span&gt;

&lt;span class="c"&gt;# Monter EFS (nécessite nfs-utils dans le Dockerfile + additionalOsCapabilities)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; mountpoint &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MOUNT_POINT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;mount &lt;span class="nt"&gt;-t&lt;/span&gt; nfs4 &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;nfsvers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4.1,rsize&lt;span class="o"&gt;=&lt;/span&gt;1048576,wsize&lt;span class="o"&gt;=&lt;/span&gt;1048576,hard,timeo&lt;span class="o"&gt;=&lt;/span&gt;600,retrans&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EFS_DNS&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:/"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MOUNT_POINT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;chown &lt;/span&gt;developer:developer &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MOUNT_POINT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Lancer OpenVSCode Server en tant que developer&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;su - developer &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"/opt/vscode/bin/openvscode-server &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --host 0.0.0.0 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --port 8080 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --without-connection-token &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
    --default-folder /home/developer/workspace"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour activer les capabilities OS nécessaires au montage NFS, ajoutez &lt;code&gt;--additional-os-capabilities&lt;/code&gt; lors de la création de l'image :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda-microvms create-microvm-image &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; vscode-dev-environment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--code-artifact&lt;/span&gt; &lt;span class="nv"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s3://my-microvm-artifacts/vscode-microvm.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-image-arn&lt;/span&gt; arn:aws:lambda:eu-west-1:aws:microvm-image:al2023-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--build-role-arn&lt;/span&gt; arn:aws:iam::123456789012:role/MicroVMBuildRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--environment-variables&lt;/span&gt; &lt;span class="s1"&gt;'{"EFS_FILE_SYSTEM_ID":"fs-0abc123def456"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--additional-os-capabilities&lt;/span&gt; &lt;span class="s1"&gt;'["ALL"]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Étape 4 : packager et créer l'image MicroVM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Packager le code source&lt;/span&gt;
zip &lt;span class="nt"&gt;-r&lt;/span&gt; vscode-microvm.zip Dockerfile entrypoint.sh

&lt;span class="c"&gt;# Uploader sur S3&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;vscode-microvm.zip s3://my-microvm-artifacts/vscode-microvm.zip

&lt;span class="c"&gt;# Créer l'image MicroVM&lt;/span&gt;
aws lambda-microvms create-microvm-image &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; vscode-dev-environment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--code-artifact&lt;/span&gt; &lt;span class="nv"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s3://my-microvm-artifacts/vscode-microvm.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-image-arn&lt;/span&gt; arn:aws:lambda:eu-west-1:aws:microvm-image:al2023-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--build-role-arn&lt;/span&gt; arn:aws:iam::123456789012:role/MicroVMBuildRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--environment-variables&lt;/span&gt; &lt;span class="s1"&gt;'{"EFS_FILE_SYSTEM_ID":"fs-0abc123def456"}'&lt;/span&gt;

&lt;span class="c"&gt;# Vérifier l'état du build&lt;/span&gt;
aws lambda-microvms get-microvm-image &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image-identifier&lt;/span&gt; vscode-dev-environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le build est asynchrone. L'image passe de &lt;code&gt;CREATING&lt;/code&gt; à &lt;code&gt;CREATED&lt;/code&gt; en succès, ou &lt;code&gt;CREATE_FAILED&lt;/code&gt; en cas d'erreur. Consultez les logs CloudWatch sous &lt;code&gt;/aws/lambda/microvms/vscode-dev-environment&lt;/code&gt; pour le diagnostic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Étape 5 : lancer l'environnement de développement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Créer un network connector VPC pour accéder à EFS (une seule fois)&lt;/span&gt;
aws lambda-core create-network-connector &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; dev-vpc-egress &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
    "VpcEgressConfiguration": {
      "SubnetIds": ["subnet-private-a"],
      "SecurityGroupIds": ["sg-dev-microvm"],
      "NetworkProtocol": "IPv4",
      "AssociatedComputeResourceTypes": ["MicroVm"]
    }
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--operator-role&lt;/span&gt; arn:aws:iam::123456789012:role/NetworkConnectorOperatorRole

&lt;span class="c"&gt;# Lancer la MicroVM avec politique d'idle intelligente&lt;/span&gt;
aws lambda-microvms run-microvm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image-identifier&lt;/span&gt; arn:aws:lambda:eu-west-1:123456789012:microvm-image:vscode-dev-environment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--execution-role-arn&lt;/span&gt; arn:aws:iam::123456789012:role/DevMicroVMRole &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ingress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--egress-network-connectors&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:123456789012:network-connector:dev-vpc-egress"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--idle-policy&lt;/span&gt; &lt;span class="s1"&gt;'{"maxIdleDurationSeconds":3600,"suspendedDurationSeconds":1800,"autoResumeEnabled":true}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--maximum-duration-in-seconds&lt;/span&gt; 28800
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La réponse contient l'endpoint HTTPS dédié et le MicroVM ID :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"microvmId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mvm-01234567-abcd-ef01-2345-6789abcdef01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PENDING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour vous connecter, générez un token d'authentification :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Générer un token valide 8h (durée max de la session)&lt;/span&gt;
aws lambda-microvms create-microvm-auth-token &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--microvm-identifier&lt;/span&gt; mvm-01234567-abcd-ef01-2345-6789abcdef01 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--expiration-in-minutes&lt;/span&gt; 480 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allowed-ports&lt;/span&gt; &lt;span class="s1"&gt;'[{"port":8080}]'&lt;/span&gt;

&lt;span class="c"&gt;# Accéder à l'IDE dans le navigateur :&lt;/span&gt;
&lt;span class="c"&gt;# https://mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws&lt;/span&gt;
&lt;span class="c"&gt;# Header requis : X-aws-proxy-auth: &amp;lt;token&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La politique d'idle est configurée pour suspendre la MicroVM après &lt;strong&gt;1 heure d'inactivité&lt;/strong&gt;, la garder suspendue &lt;strong&gt;30 minutes&lt;/strong&gt;, et la reprendre automatiquement au prochain accès HTTP. Pour un développeur qui fait des pauses café ou des réunions, la MicroVM se suspend et se réveille de manière transparente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Étape 6 : automatiser avec une Step Function
&lt;/h3&gt;

&lt;p&gt;Pour une équipe, vous pouvez automatiser la provision avec une Step Function déclenchée par un portail interne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Provision dev environment on demand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"StartAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RunMicroVM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"States"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"RunMicroVM"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:states:::aws-sdk:lambdamicrovms:runMicrovm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ImageIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:123456789012:microvm-image:vscode-dev-environment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ExecutionRoleArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::123456789012:role/DevMicroVMRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"IngressNetworkConnectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:aws:network-connector:aws-network-connector:ALL_INGRESS"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"EgressNetworkConnectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:eu-west-1:123456789012:network-connector:dev-vpc-egress"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"IdlePolicy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"MaxIdleDurationSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"SuspendedDurationSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"AutoResumeEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"MaximumDurationInSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28800&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ResultPath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$.microvm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NotifyDeveloper"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"NotifyDeveloper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:states:::sns:publish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"TopicArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sns:eu-west-1:123456789012:dev-notifications"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Message.$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"States.Format('Votre IDE est prêt : {}', $.microvm.Endpoint)"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"End"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pourquoi le suspend/resume change la donne (et EFS en option)
&lt;/h3&gt;

&lt;p&gt;Le point clé de cette architecture est le &lt;strong&gt;modèle suspend/resume natif&lt;/strong&gt; de Lambda MicroVMs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pendant le suspend&lt;/strong&gt; : le snapshot Firecracker préserve l'intégralité de la mémoire et du disque. Votre code, vos fichiers ouverts dans VS Code, votre historique terminal — tout est intact au resume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La MicroVM est éphémère mais stateful&lt;/strong&gt; : tant qu'elle n'est pas terminée, le workspace persiste entre les sessions suspend/resume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EFS pour la persistance long-terme&lt;/strong&gt; : si vous avez besoin que le code survive à la terminaison de la MicroVM (après 8h max ou idle trop long), ajoutez EFS comme décrit à l'étape 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sans EFS, le workflow est :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;La MicroVM tourne → vous codez&lt;/li&gt;
&lt;li&gt;Idle 1h → Lambda suspend (0\$ compute, snapshot préservé)&lt;/li&gt;
&lt;li&gt;Vous revenez → auto-resume en ~1-2 secondes, tout est là&lt;/li&gt;
&lt;li&gt;Après 8h ou terminaison → workspace perdu&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Avec EFS :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Même workflow, mais le code est sur un montage NFS&lt;/li&gt;
&lt;li&gt;Terminaison → vous relancez une MicroVM, EFS est remonté, code intact&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partage possible&lt;/strong&gt; : plusieurs développeurs peuvent monter le même EFS (ou des Access Points différents) pour du pair programming&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Étape 7 : proxy local pour l'accès navigateur
&lt;/h3&gt;

&lt;p&gt;Un navigateur ne peut pas injecter le header &lt;code&gt;X-aws-proxy-auth&lt;/code&gt; sur chaque requête HTTP et WebSocket. Pour accéder à OpenVSCode Server depuis votre poste, vous avez besoin d'un &lt;strong&gt;proxy local&lt;/strong&gt; qui :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Écoute sur &lt;code&gt;http://localhost:8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Forward chaque requête vers l'endpoint HTTPS de la MicroVM en ajoutant le token d'authentification&lt;/li&gt;
&lt;li&gt;Gère les upgrades WebSocket (indispensables pour le terminal et le LSP de VS Code) en passant le token via les subprotocols &lt;code&gt;lambda-microvms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Renouvelle automatiquement le token avant expiration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voici un proxy minimal en Node.js :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// proxy.mjs — Proxy local d'authentification Lambda MicroVM&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:https&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MICROVM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MICROVM_ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MICROVM_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MICROVM_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eu-west-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LOCAL_PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TOKEN_EXPIRATION_MINUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TOKEN_EXPIRATION&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;60&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokenExpiresAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`aws lambda-microvms create-microvm-auth-token \
    --microvm-identifier &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MICROVM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; \
    --expiration-in-minutes &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;TOKEN_EXPIRATION_MINUTES&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; \
    --allowed-ports '[{"allPorts":{}}]' \
    --region &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; --output json`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-aws-proxy-auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;tokenExpiresAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TOKEN_EXPIRATION_MINUTES&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenExpiresAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getEndpoint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MICROVM_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MICROVM_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`aws lambda-microvms get-microvm --microvm-identifier &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MICROVM_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; --region &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; --output json`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getEndpoint&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Forward HTTP&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-aws-proxy-auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;502&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bad Gateway&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Forward WebSocket upgrades&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleUpgrade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;upgrade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;websocket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Injecter le token via subprotocols WebSocket&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-websocket-protocol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-websocket-protocol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda-microvms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`lambda-microvms.authentication.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda-microvms.port.8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-aws-proxy-auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxySocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxyHead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Filtrer les subprotocols lambda-microvms de la réponse&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;responseHead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HTTP/1.1 101 Switching Protocols&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sec-websocket-protocol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda-microvms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;responseHead&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;\r\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;responseHead&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\r\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;responseHead&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHead&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyHead&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyHead&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;proxySocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxySocket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;proxySocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;proxySocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`HTTP/1.1 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\r\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\r\n`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;proxyRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="nx"&gt;proxyReq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleUpgrade&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LOCAL_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`MicroVM proxy → http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;LOCAL_PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; → https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilisation :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Lancer le proxy&lt;/span&gt;
&lt;span class="nv"&gt;MICROVM_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mvm-01234567-abcd-ef01-2345-6789abcdef01 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;MICROVM_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mvm-01234567-abcd-ef01-2345-6789abcdef01.lambda-microvm.eu-west-1.on.aws &lt;span class="se"&gt;\&lt;/span&gt;
  node proxy.mjs

&lt;span class="c"&gt;# Ouvrir VS Code dans le navigateur&lt;/span&gt;
open http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le proxy renouvelle le token 5 minutes avant expiration, gère le protocole WebSocket avec les subprotocols &lt;code&gt;lambda-microvms&lt;/code&gt; (requis par l'endpoint), et filtre ces subprotocols de la réponse pour ne pas perturber VS Code côté client.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pourquoi un proxy local ?&lt;/strong&gt; L'endpoint MicroVM est un service managé par Lambda avec authentification JWE obligatoire — il n'est pas possible de placer un ALB ou un CloudFront devant. Il n'y a pas non plus d'option d'accès non authentifié ni de custom domain. Le proxy local (ou un proxy déployé sur une instance/container dans votre VPC) est le pattern d'accès navigateur recommandé pour les cas interactifs comme un IDE.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Comparaison avec les alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Critère&lt;/th&gt;
&lt;th&gt;Cloud9 (ancien)&lt;/th&gt;
&lt;th&gt;CodeCatalyst Dev Env&lt;/th&gt;
&lt;th&gt;Lambda MicroVM + VS Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Coût idle&lt;/td&gt;
&lt;td&gt;Instance EC2 24/7&lt;/td&gt;
&lt;td&gt;Stoppé = gratuit&lt;/td&gt;
&lt;td&gt;Suspendu = ~0\$ compute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Démarrage&lt;/td&gt;
&lt;td&gt;~60s (boot EC2)&lt;/td&gt;
&lt;td&gt;~30-60s&lt;/td&gt;
&lt;td&gt;~2s (resume snapshot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isolation&lt;/td&gt;
&lt;td&gt;Shared tenancy&lt;/td&gt;
&lt;td&gt;Container&lt;/td&gt;
&lt;td&gt;Firecracker VM dédiée&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personnalisation&lt;/td&gt;
&lt;td&gt;Limitée&lt;/td&gt;
&lt;td&gt;Devfile&lt;/td&gt;
&lt;td&gt;Dockerfile complet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistance&lt;/td&gt;
&lt;td&gt;EBS&lt;/td&gt;
&lt;td&gt;EBS&lt;/td&gt;
&lt;td&gt;Suspend/resume + EFS optionnel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Durée max session&lt;/td&gt;
&lt;td&gt;Illimitée&lt;/td&gt;
&lt;td&gt;16h (puis stop auto)&lt;/td&gt;
&lt;td&gt;8h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non (ARM64 uniquement)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Considérations de sécurité et bonnes pratiques
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;IAM least privilege&lt;/strong&gt; : le rôle d'exécution ne doit avoir accès qu'aux services nécessaires au développeur. Le rôle de l'opérateur network connector se limite à la création d'ENIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC egress connector&lt;/strong&gt; : routez le trafic sortant via un subnet privé avec un NAT Gateway pour l'accès internet, et des security groups pour contrôler l'accès aux ressources internes (EFS, RDS...)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentification&lt;/strong&gt; : chaque requête vers l'endpoint MicroVM nécessite un token JWE (&lt;code&gt;X-aws-proxy-auth&lt;/code&gt;). Scopez les tokens sur le port 8080 uniquement et avec une expiration courte pour les environnements partagés&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chiffrement&lt;/strong&gt; : EFS chiffré at-rest (KMS) + in-transit (NFS over TLS). Le trafic entre le client et l'endpoint MicroVM est toujours chiffré en TLS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt; : les logs de build et d'exécution sont dans CloudWatch sous &lt;code&gt;/aws/lambda/microvms/&amp;lt;image-name&amp;gt;&lt;/code&gt;. Chaque &lt;code&gt;run-microvm&lt;/code&gt; est tracé dans CloudTrail&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Lambda MicroVMs n'est pas juste un nouveau service — c'est un changement de paradigme dans la façon dont on conçoit les environnements de calcul éphémères sur AWS. La combinaison d'une isolation hardware Firecracker, d'un démarrage quasi-instantané depuis snapshot, et d'un modèle de facturation à 0\$ pendant la suspension ouvre des possibilités qui étaient auparavant réservées à des startups spécialisées comme E2B ou Daytona.&lt;/p&gt;

&lt;p&gt;Que ce soit pour des bastions JIT qui réduisent votre surface d'attaque, des sandboxes d'agents IA qui exécutent du code non fiable en toute sécurité, ou un IDE cloud DIY qui remplace Cloud9 — Lambda MicroVMs mérite une place dans votre boîte à outils architecturale.&lt;/p&gt;

&lt;p&gt;Le tutoriel présenté ici avec OpenVSCode Server + EFS est un point de départ. Vous pouvez l'enrichir avec du pair programming (multiple Access Points), des templates par projet (une image MicroVM par stack technique), ou même un système de facturation interne par développeur grâce aux tags CloudWatch.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/aws/run-isolated-sandboxes-with-full-lifecycle-control-aws-lambda-introduces-microvms/" rel="noopener noreferrer"&gt;Annonce officielle AWS Lambda MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/lambda/lambda-microvms/" rel="noopener noreferrer"&gt;Page produit Lambda MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-microvms-guide.html" rel="noopener noreferrer"&gt;Documentation Lambda MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/microvm-api/" rel="noopener noreferrer"&gt;API Reference Lambda MicroVMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/microvms-images.html" rel="noopener noreferrer"&gt;MicroVM Images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/microvms-networking.html" rel="noopener noreferrer"&gt;Networking — Network Connectors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gitpod-io/openvscode-server" rel="noopener noreferrer"&gt;OpenVSCode Server — Gitpod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/efs/latest/ug/whatisefs.html" rel="noopener noreferrer"&gt;Amazon EFS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>devops</category>
    </item>
    <item>
      <title>Déléguer les services AWS liés à l'organisation sur des comptes membres</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:12:06 +0000</pubDate>
      <link>https://dev.to/sylvainbruas/deleguer-les-services-aws-lies-a-lorganisation-sur-des-comptes-membres-4bnn</link>
      <guid>https://dev.to/sylvainbruas/deleguer-les-services-aws-lies-a-lorganisation-sur-des-comptes-membres-4bnn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4lrlziyylfjuiosw173.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4lrlziyylfjuiosw173.webp" alt="Déléguer les services AWS liés à l'organisation sur des comptes membres" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Le compte AWS payeur est la brique centrale de votre landing zone. C'est ce compte qui détient les informations de facturation ainsi que la racine de l'organisation.&lt;/p&gt;

&lt;p&gt;Au fil des années, AWS a ajouté de nombreuses fonctionnalités autour de l'organisation pour pouvoir travailler à l'échelle et faciliter la maintenance de la landing zone. Le compte payeur devenait de plus en plus stratégique au fil des services ajoutés.&lt;/p&gt;

&lt;p&gt;En 2020, AWS a mis en place pour la première fois la délégation de compte vers un compte membre (pour le service &lt;a href="https://aws.amazon.com/blogs/aws/new-use-aws-iam-access-analyzer-in-aws-organizations/" rel="noopener noreferrer"&gt;IAM Access Analyzer&lt;/a&gt;). Cela a permis de déplacer les responsabilités pour ce service, et au fil des mois de nouveaux services ont profité de la délégation pour s'affranchir de la contrainte du compte payeur.&lt;/p&gt;

&lt;p&gt;Mes clients font preuve de prudence quand on parle du compte payeur, une liste très limitée d'utilisateurs ont accès à ce compte, avec un respect strict du moindre privilège.&lt;/p&gt;

&lt;p&gt;Nous allons voir les services principaux qui peuvent être délégués, et nous allons les regrouper pour optimiser leur utilisation pour chaque équipe, et pour sécuriser ces services plus facilement en les déléguant sur les bons comptes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qu'est-ce que la Délégation de Services AWS ?
&lt;/h2&gt;

&lt;p&gt;La délégation de services AWS est le mécanisme qui permet à un service AWS (comme &lt;a href="https://docs.aws.amazon.com//config/latest/developerguide/WhatIsConfig.html" rel="noopener noreferrer"&gt;AWS Config&lt;/a&gt; ou &lt;a href="https://docs.aws.amazon.com//systems-manager/latest/userguide/what-is-systems-manager.html" rel="noopener noreferrer"&gt;AWS Systems Manager&lt;/a&gt;) d'effectuer des opérations et de gérer des ressources au nom de votre organisation, et surtout, de désigner un compte membre spécifique pour administrer ce service pour l'ensemble de l'organisation.&lt;/p&gt;

&lt;p&gt;Il existe deux concepts clés à comprendre :&lt;/p&gt;

&lt;h3&gt;
  
  
  Accès de confiance (Trusted Access)
&lt;/h3&gt;

&lt;p&gt;C'est la première étape. Lorsque vous activez l'accès de confiance pour un service AWS avec AWS &lt;a href="https://docs.aws.amazon.com//organizations/latest/userguide/orgs_introduction.html" rel="noopener noreferrer"&gt;Organizations&lt;/a&gt;, vous autorisez ce service à créer des rôles liés au service (Service-Linked Roles) dans vos comptes membres. Ces rôles permettent au service d'accéder aux ressources nécessaires pour fonctionner au niveau de l'organisation. C'est une permission large, mais nécessaire pour l'intégration. Par exemple, si vous activez l'accès de confiance pour AWS Config, AWS Config pourra déployer des règles et collecter des données de conformité dans tous les comptes de votre organisation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Administrateur Délégué (Delegated Administrator)
&lt;/h3&gt;

&lt;p&gt;C'est le cœur de la délégation. Au lieu que le compte de gestion (Management Account) soit le seul à pouvoir administrer un service pour toute l'organisation, vous pouvez désigner un compte membre spécifique comme « administrateur délégué » pour ce service. Ce compte délégué peut alors effectuer des opérations d'administration pour le service dans tous les comptes de l'organisation, sans avoir besoin d'accéder directement au compte de gestion.&lt;/p&gt;

&lt;p&gt;Imaginez le compte de gestion comme le PDG de l'entreprise. Il définit la stratégie globale. La délégation de services, c'est comme nommer un directeur de département (le compte administrateur délégué) qui gère les opérations quotidiennes de son département (le service AWS) pour toutes les filiales (les comptes membres), sans que le PDG n'ait à s'immiscer dans chaque détail opérationnel. Cela permet de décharger le compte de gestion de tâches opérationnelles et de renforcer le principe du moindre privilège.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les services liés à l'organisation et les possibilités de délégation
&lt;/h2&gt;

&lt;p&gt;Nous pouvons trouver la liste complète de tous les services pouvant être délégués ici : &lt;a href="https://docs.aws.amazon.com/fr_fr/organizations/latest/userguide/orgs_integrate_services_list.html" rel="noopener noreferrer"&gt;Services AWS que vous pouvez utiliser avec AWS Organizations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nous allons définir quelle équipe de l'entreprise pourrait être responsable de chaque service, pour ensuite déployer la délégation de service sur les comptes correspondants. Nous allons choisir en priorité les équipes qui effectueront les actions sur les comptes AWS et le maintien en condition opérationnelle (MCO / RUN).&lt;/p&gt;

&lt;p&gt;Pour plusieurs services, nous pouvons configurer une délégation sur plusieurs comptes AWS. Je vous conseille de limiter à un compte la délégation pour que l'on soit aligné avec le RACI (Responsible, Accountable, Consulted et Informed). Chaque fonctionnalité doit être prise en charge (Accountable) par une équipe pour éviter tout conflit ou zone non couverte (« Ce n'est pas ma responsabilité mais celle de l'autre équipe »).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Equipes possibles&lt;/th&gt;
&lt;th&gt;Equipe responsable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS Account Management&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Backup&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Billing and Cost Management&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Systems Manager&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://docs.aws.amazon.com//cloudformation/latest/userguide/Welcome.html" rel="noopener noreferrer"&gt;AWS CloudFormation&lt;/a&gt; StackSets&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.aws.amazon.com//cloudtrail/latest/userguide/cloudtrail-user-guide.html" rel="noopener noreferrer"&gt;AWS CloudTrail&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Sécurité (1)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.aws.amazon.com//cloudwatch/latest/monitoring/WhatIsCloudWatch.html" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//compute-optimizer/latest/ug/what-is-compute-optimizer.html" rel="noopener noreferrer"&gt;Compute Optimizer&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;FinOps ou Opérations&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Config&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations (2)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Config Aggregator&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations (2)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Cost Optimization Hub&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.aws.amazon.com//guardduty/latest/ug/what-is-guardduty.html" rel="noopener noreferrer"&gt;Amazon GuardDuty&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Health&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root Management pour comptes membres&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Sécurité (3)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//license-manager/latest/userguide/license-manager.html" rel="noopener noreferrer"&gt;License Manager&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;FinOps ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations (4)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//vpc/latest/network-manager/what-is-network-manager.html" rel="noopener noreferrer"&gt;Network Manager&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Réseau ou Opérations&lt;/td&gt;
&lt;td&gt;Réseau&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//resource-explorer/latest/userguide/what-is-resource-explorer.html" rel="noopener noreferrer"&gt;Resource Explorer&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;FinOps ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations (5)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.aws.amazon.com//AmazonS3/latest/userguide/storage_lens.html" rel="noopener noreferrer"&gt;Amazon Simple Storage Service (S3) Storage Lens&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;FinOps ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations (5)
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.aws.amazon.com//securityhub/latest/userguide/what-is-securityhub.html" rel="noopener noreferrer"&gt;AWS Security Hub&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//servicecatalog/latest/adminguide/introduction.html" rel="noopener noreferrer"&gt;Service Catalog&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//singlesignon/latest/userguide/what-is.html" rel="noopener noreferrer"&gt;IAM Identity Center&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Sécurité ou Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS User Notifications&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;td&gt;Opérations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS &lt;a href="https://docs.aws.amazon.com//awssupport/latest/user/trusted-advisor.html" rel="noopener noreferrer"&gt;Trusted Advisor&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;FinOps ou Opérations&lt;/td&gt;
&lt;td&gt;FinOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html" rel="noopener noreferrer"&gt;Amazon Virtual Private Cloud (VPC) IP Address Manager&lt;/a&gt; (IPAM)&lt;/td&gt;
&lt;td&gt;Réseau&lt;/td&gt;
&lt;td&gt;Réseau&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon &lt;a href="https://docs.aws.amazon.com//vpc/latest/reachability/what-is-reachability-analyzer.html" rel="noopener noreferrer"&gt;VPC Reachability Analyzer&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Réseau ou Opérations&lt;/td&gt;
&lt;td&gt;Réseau&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon &lt;a href="https://docs.aws.amazon.com//security-lake/latest/userguide/what-is-security-lake.html" rel="noopener noreferrer"&gt;Security Lake&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a&gt;(1)&lt;/a&gt; : Le choix sur ce point est assez complexe, et les 2&lt;br&gt;
équipes proposées pourraient parfaitement être responsables de ce point. Cette&lt;br&gt;
fonctionnalité touche les la gestion des logs d'audit, ce qui reste un point&lt;br&gt;
très sensible, et donc nous allons privilégier l'équipe sécurité qui est garante&lt;br&gt;
des données critiques, sensibles et confidentielles.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;(2)&lt;/a&gt; : Malgré le fait que AWS Config soit un service de&lt;br&gt;
sécurité et indispensable pour la gouvernance, il est plus intéressant de le&lt;br&gt;
déléguer à l'équipe opérations. L'équipe sécurité va définir les objectifs (en&lt;br&gt;
se basant sur les obligations légales et des frameworks tels que PCI-DSS ou NIST&lt;br&gt;
par exemple) et lister les tests de conformité à mettre en place. Les Opérations&lt;br&gt;
vont implémenter ces demandes, rajouter d'autres tests, ajouter des remédiations&lt;br&gt;
automatiques dans certains cas. En cas de non-conformité, les opérations seront&lt;br&gt;
alertées et seront responsables de la remise en conformité de la ressource qui a&lt;br&gt;
créé l'alarme. L'équipe sécurité sera informée de ces actions.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;(3)&lt;/a&gt; : Le choix sur ce point est encore complexe, et les 2&lt;br&gt;
équipes proposées pourraient parfaitement être responsables de ce point. J'ai&lt;br&gt;
choisi de proposer plutôt l'équipe sécurité car dans les grands groupes où j'ai&lt;br&gt;
pu intervenir, la taille et la formation des équipes sécurité était suffisante&lt;br&gt;
pour répondre aux demandes (réactivation exceptionnelle des comptes root ou&lt;br&gt;
déblocage Amazon Simple Queue Service (SQS) et S3). Cette fonctionnalité touche les comptes root, ce qui reste&lt;br&gt;
un point très sensible, et donc nous allons privilégier l'équipe sécurité qui&lt;br&gt;
est garante des données critiques, sensibles et confidentielles.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;(4)&lt;/a&gt; : Les licences sont un point qui doit être précisément&lt;br&gt;
suivi par les FinOps pour éviter toute pénalité. Ce sont les équipes opérations&lt;br&gt;
qui vont déployer les licences et faire le suivi de leur utilisation. Il est&lt;br&gt;
donc nécessaire que les opérations soient responsables de ce point (Responsible)&lt;br&gt;
et qu'elles partagent les informations de suivi avec les FinOps qui sont&lt;br&gt;
validateurs et responsables de l'utilisation (Accountable).&lt;/p&gt;

&lt;p&gt;&lt;a&gt;(5)&lt;/a&gt; : Cette fonctionnalité peut être utile pour les FinOps,&lt;br&gt;
mais les utilisateurs principaux seront dans l'équipe opérations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxmpebqm4sbvkpecrk0h.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxmpebqm4sbvkpecrk0h.webp" alt="répartition des services par équipe" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Avantages de la Délégation de Services
&lt;/h2&gt;

&lt;p&gt;La délégation de services apporte de nombreux bénéfices à votre organisation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gouvernance centralisée et simplifiée&lt;/strong&gt; : Le compte de gestion reste léger et se concentre sur la gouvernance de haut niveau (création de comptes, OUs, SCPs). Les opérations quotidiennes et la gestion des services sont déléguées à des comptes membres spécialisés, réduisant la charge sur le compte racine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sécurité améliorée&lt;/strong&gt; : Réduit la surface d'attaque du compte de gestion en limitant les opérations directes sur celui-ci. La gestion des permissions est plus aisée dans les comptes membres, car la portée de chacun est réduite. Cela permet une application cohérente des politiques de sécurité et une meilleure posture globale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principe du moindre privilège&lt;/strong&gt; : Renforce ce principe fondamental de sécurité. Les équipes n'ont accès qu'aux services nécessaires à leurs missions. Par exemple, le compte de gestion n'a pas besoin d'accéder aux données de sécurité agrégées, c'est le compte de sécurité délégué qui le fait.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Évolutivité&lt;/strong&gt; : Facilite l'ajout de nouveaux comptes à l'organisation, car ils héritent automatiquement des configurations déléguées des services, réduisant le temps de mise en conformité des nouveaux environnements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Défis liés à la délégation
&lt;/h2&gt;

&lt;p&gt;Malgré ses nombreux avantages, la délégation de services présente certaines limites.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexité initiale&lt;/strong&gt; : La mise en place demande une bonne compréhension d'AWS Organizations, IAM, et des services spécifiques que vous souhaitez déléguer. Ce n'est pas encore une solution « plug-and-play » et nécessite une planification minutieuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dépendance au compte administrateur délégué&lt;/strong&gt; : Le compte désigné comme administrateur délégué devient un point de contrôle critique pour le service qu'il gère. Sa sécurité est primordiale. Une compromission de ce compte peut avoir des répercussions sur toute l'organisation pour le service délégué.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portée des permissions&lt;/strong&gt; : Il est crucial de comprendre précisément quelles permissions le service délégué obtient et ce que l'administrateur délégué peut faire. Une mauvaise configuration peut entraîner des permissions excessives ou des lacunes de sécurité.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pas tous les services ne supportent la délégation&lt;/strong&gt; : C'est une limite importante. Avant de planifier, vérifiez toujours la documentation AWS pour confirmer si le service que vous souhaitez déléguer prend en charge la fonctionnalité "Delegated Administrator" ou "Trusted Access" avec AWS Organizations. La liste des services évolue régulièrement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact sur les SCPs&lt;/strong&gt; : Les SCPs peuvent toujours restreindre les actions des administrateurs délégués. Assurez-vous que vos SCPs n'empêchent pas les actions nécessaires à la gestion déléguée du service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recommandations
&lt;/h2&gt;

&lt;p&gt;Pour tirer le meilleur parti de la délégation de services et éviter les pièges, suivez ces bonnes pratiques :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Planification Rigoureuse&lt;/strong&gt; : Ne vous lancez pas à l'aveugle. Définissez clairement les rôles, les responsabilités, les services à déléguer et les comptes qui seront administrateurs délégués. Gardez en tête que la transformation du modèle opérationnel et des équipes reste un des grands challenges de la délégation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principe du Moindre Privilège (encore et toujours !)&lt;/strong&gt; : Appliquez des politiques IAM strictes aux rôles et utilisateurs dans le compte administrateur délégué. Ils ne devraient avoir que les permissions nécessaires pour administrer le service délégué, et rien de plus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surveillance&lt;/strong&gt; : Utilisez AWS CloudTrail pour auditer toutes les actions effectuées par les services délégués et les administrateurs délégués.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatisation (IaC)&lt;/strong&gt; : Utilisez l'Infrastructure as Code (IaC) pour gérer la configuration d'AWS Organizations et la délégation de services. Cela assure la cohérence, la reproductibilité et facilite les mises à jour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt; : Documentez minutieusement votre stratégie de délégation, les services délégués, les comptes administrateurs et les processus associés. C'est vital pour la maintenabilité et la compréhension par les équipes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formation des équipes&lt;/strong&gt; : Assurez-vous que vos équipes comprennent le nouveau modèle de gouvernance et leurs responsabilités dans un environnement délégué.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt; : Testez toujours vos configurations de délégation dans un environnement non-production avant de les déployer à grande échelle. Validez que les services fonctionnent comme prévu et que les permissions sont correctement appliquées.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;La délégation de services AWS est intéressante et peut devenir une nécessité pour une organisation souhaitant opérer sur AWS à grande échelle de manière sécurisée, conforme et efficace. Pour des organisations plus modestes, qui n'ont pas d'obligations légales ou qui n'ont pas d'équipes opérationnelles ou de sécurité de taille suffisante, il peut être intéressant de rester sur un modèle centralisé.&lt;/p&gt;

&lt;p&gt;Dans tous les cas, une gestion rigoureuse des permissions IAM est nécessaire pour assurer la sécurité de la landing zone.&lt;/p&gt;

&lt;p&gt;Mon conseil : commencez par un service clé comme AWS Config ou AWS CloudFormation StackSets, maîtrisez le concept, puis étendez progressivement à d'autres services. La route vers une gouvernance cloud optimale est un marathon, pas un sprint. Investissez dans la planification et l'automatisation, et vous récolterez les fruits d'un environnement AWS bien géré et sécurisé.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>gouvernance</category>
      <category>securite</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Build Games Challenge: Une bonne raison pour tester la puissance d'amazon Q</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:11:32 +0000</pubDate>
      <link>https://dev.to/sylvainbruas/build-games-challenge-une-bonne-raison-pour-tester-la-puissance-damazon-q-2okn</link>
      <guid>https://dev.to/sylvainbruas/build-games-challenge-une-bonne-raison-pour-tester-la-puissance-damazon-q-2okn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsylvain.bruas.fr%2Fstatic%2F2025%2F06%2FBuild_a_game.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsylvain.bruas.fr%2Fstatic%2F2025%2F06%2FBuild_a_game.webp" alt="Build Games Challenge: Créons un jeu vidéo avec l'aide d'Amazon&lt;br&gt;
  Q" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;J'ai découvert hier ce challenge et, étant friand de rétro gaming, j'ai pensé que cela serait un bon support pour aborder également l'utilisation d'&lt;a href="https://docs.aws.amazon.com//amazonq/latest/qdeveloper-ug/" rel="noopener noreferrer"&gt;Amazon Q&lt;/a&gt; Developer CLI.&lt;/p&gt;

&lt;p&gt;J'ai décidé de faire un hommage à un jeu qui m'a frustré quand j'étais en primaire, R-Type 2 sur Nintendo Super NES ( &lt;a href="https://en.wikipedia.org/wiki/R-Type_II" rel="noopener noreferrer"&gt;Description&lt;/a&gt; ).&lt;/p&gt;

&lt;h2&gt;
  
  
  Dépôt GIT du jeu
&lt;/h2&gt;

&lt;p&gt;Vous trouverez ici tous les fichiers du jeu, ainsi que toutes les étapes intermédiaires depuis la création : &lt;strong&gt;&lt;a href="https://github.com/sylvainbruas/r-type-like" rel="noopener noreferrer"&gt;https://github.com/sylvainbruas/r-type-like&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mécanique du jeu
&lt;/h2&gt;

&lt;p&gt;Le jeu R-Type 2 était très simple et efficace :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5 niveaux à traverser, chacun se terminant par un boss.&lt;/li&gt;
&lt;li&gt;Des environnements 8 bits très travaillés&lt;/li&gt;
&lt;li&gt;Des groupes d'ennemis à détruire&lt;/li&gt;
&lt;li&gt;Des bonus, de puissance ou des vies supplémentaires (très utile !)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C'était un jeu très exigeant et punitif. Même si 5 niveaux donnent l'impression d'un jeu très court, la difficulté est élevée, et passer le 2e niveau vous demandera déjà une bonne connaissance des patterns des ennemis pour vous en sortir.&lt;/p&gt;

&lt;p&gt;Ma version sera bien plus simple, le but étant de montrer que l'on peut aller très vite et très loin juste en fournissant les bonnes informations à Amazon Q.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup de mon environnement
&lt;/h2&gt;

&lt;p&gt;J'ai commencé par installer Amazon Q Developer en suivant la &lt;a href="https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-installing.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, puis je me suis connecté avec mon builder ID.&lt;/p&gt;

&lt;p&gt;Ce n'est pas le premier projet que je fais avec cet outil, j'ai donc créé un prompt que j'exécute pour chaque nouveau projet :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Initialise le projet avec un README en markdown, ajoute un suivi avec Git, crée un fichier questions.txt qui listera les demandes dans l'ordre et contiendra également une synthèse des actions pour y répondre. Après chaque action, crée un ou plusieurs commits Git pour regrouper les modifications qui ont du sens ensemble, avec un message de commit explicite.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;J'ai ajouté les points suivants à mon prompt :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tous les messages doivent être en français. Ajoute également des tests pour chaque nouvelle fonctionnalité que tu mets en place. Initialise-moi un README pour ce projet et pour les sous-répertoires où cela te semble nécessaire, et mets-le à jour régulièrement. Enfin, après avoir fait une correction, lance les tests pour vérifier que tout est en ordre.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maintenant que j'ai partagé mes attentes pour l'organisation du projet, donnons le sujet à Amazon Q :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Créer un jeu inspiré de R-TYPE2 sur Super Nintendo. Ce jeu doit être jouable sur le navigateur. Laisser le choix de la bibliothèque la plus efficace pour faire cela. Il y aura 5 niveaux, chacun se terminant par un boss, et un système de points.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Je me retrouve donc avec la structure de projet suivante :&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokup42prfppbrsu0605a.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokup42prfppbrsu0605a.webp" alt="Structure du projet" width="356" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus !&lt;/strong&gt; Amazon Q a eu la gentillesse de me faire des scripts de lancement du jeu.&lt;br&gt;
J'ai des explications très claires dans le README, et toutes les informations pour faire le setup du projet dans SETUP.md.&lt;/p&gt;

&lt;p&gt;Je n'aurais pas fait une documentation si complète, et la rédiger m'aurait mis de mauvaise humeur car ce n'est pas la partie que je préfère. Avec cet outil, je délègue ces tâches, et il ne me reste plus qu'à vérifier que le rendu est au niveau de mes attentes.&lt;/p&gt;

&lt;p&gt;&lt;br&gt; Si le résultat ne me convient pas, je prends du recul, et je me pose les&lt;br&gt;
questions suivantes : - Suis-je vraiment clair sur ma demande ? - Est-ce qu'un&lt;br&gt;
humain aurait pu comprendre ma demande de cette manière ?&lt;/p&gt;

&lt;p&gt;Dans 90% des cas, effectivement j'ai fait un prompt trop vague et rapide. Je propose donc un second prompt pour corriger la demande, soit en la précisant, soit en la découpant en plusieurs parties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nouvelle Compétence Débloquée&lt;/strong&gt; : Communication avancée !&lt;/p&gt;

&lt;p&gt;En travaillant de cette manière, j'ai pu également améliorer la communication avec mes collègues. Je prends un peu plus de temps pour travailler mes formulations, le plan de mon discours, et j'ai ainsi amélioré la compréhension de mes demandes et réduit le nombre d'allers-retours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Délégation du codage : premier pas
&lt;/h2&gt;

&lt;p&gt;Dans ce projet, j'ai considéré Amazon Q comme un stagiaire. Il a de bonnes connaissances techniques et méthodologiques, mais parfois il se perd et ne prend pas de recul.&lt;br&gt;
C'est à moi de lui donner les bonnes spécifications, suffisamment claires, tout en laissant également de la place pour qu'il exprime son talent et qu'il apporte sa propre vision.&lt;/p&gt;

&lt;p&gt;À la fin du setup, j'obtiens un résultat visuel basique, une mécanique de jeu très limitée. On est loin de R-Type 2 !&lt;br&gt;
Mais vu le prompt très sommaire, c'est un début encourageant.&lt;/p&gt;

&lt;p&gt;Je recommande de diviser le projet en petits composants les plus unitaires possible, ainsi Amazon Q aura des besoins précis et nous éviterons les hallucinations ou les fonctionnalités délirantes. Il ne restera plus qu'à expliquer comment faire interagir ces composants pour avoir l'application finale.&lt;/p&gt;

&lt;p&gt;Exemple :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ajouter un système de vies pour le joueur (3 vies au début, perte d'une vie quand touché)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nous ajoutons ainsi de manière incrémentale de nouvelles fonctionnalités, qui sont testées et validées au fil de l'avancement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nouvelle Compétence Débloquée&lt;/strong&gt; : Gestion de projet agile !&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Après m'être concentré sur la partie développement, je me suis posé la question de l'hébergement.&lt;/p&gt;

&lt;p&gt;Je reste dans mon rôle Product Owner, je partage donc le besoin avec Amazon Q :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Créer un répertoire &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/" rel="noopener noreferrer"&gt;AWS CloudFormation&lt;/a&gt; et créer des templates pour déployer ce jeu sur AWS. Utiliser de préférence &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/" rel="noopener noreferrer"&gt;Amazon CloudFront&lt;/a&gt; avec &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/" rel="noopener noreferrer"&gt;Amazon Simple Storage Service (S3)&lt;/a&gt; et créer un script de build pour optimiser les assets avant de les mettre sur le cloud.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amazon Q propose une solution au-delà de ce qui est demandé, en apportant de bonnes pratiques. Il permet de déployer le projet dans 3 environnements différents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F434vnir3ix9mys2thsks.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F434vnir3ix9mys2thsks.webp" alt="Déploiement pour plusieurs environnements" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il ne reste plus qu'à relire le fichier, en utilisant nos propres compétences, pour vérifier que cette implémentation est bonne. Un vrai gain de temps quand on sait l'énergie que la lecture de la documentation CloudFormation peut demander.&lt;/p&gt;

&lt;p&gt;&lt;br&gt; Si le contenu semble correct, nous pouvons tester le code dans un&lt;br&gt;
environnement de sandbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nouvelle Compétence Débloquée&lt;/strong&gt; : Génération d'Infrastructure as Code à la vitesse de la lumière !&lt;/p&gt;

&lt;p&gt;Pour clore cette partie, ajoutons un peu de documentation, des tests et des diagrammes d'architecture.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Créer des schémas d'architecture logicielle du jeu en format draw.io.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqyfr8t1ohljyzlepch7.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqyfr8t1ohljyzlepch7.webp" alt="Flux de mise en production" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5s7063dm2fz2nfd7nno.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5s7063dm2fz2nfd7nno.webp" alt="Infrastructure AWS pour l'hébergement" width="800" height="786"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Graphisme
&lt;/h2&gt;

&lt;p&gt;Depuis mai 2025, il est possible d'utiliser Claude 4 dans Amazon Q.&lt;/p&gt;

&lt;p&gt;Cela nous permet de créer des images pour le jeu mais aussi des diagrammes d'architecture.&lt;br&gt;
Il est par exemple très pratique de demander une architecture en format draw.io, qui est facilement modifiable et où nous retrouvons les icônes AWS.&lt;br&gt;
Je n'ai pas besoin d'utiliser un autre outil qu'Amazon Q pour mon jeu. Si le résultat n'était pas suffisant, j'aurais pu étendre les fonctionnalités d'Amazon Q avec des MCPs (Model Context Protocol). Ainsi, Amazon Q aurait pu router ma demande vers un outil plus performant pour y répondre.&lt;/p&gt;

&lt;p&gt;Les résultats sont suffisants pour ce projet :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frx7ziqz2bqsmcudsd8w9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frx7ziqz2bqsmcudsd8w9.webp" alt="Les images du jeu" width="580" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;Une fonctionnalité d'Amazon Q très utile est l'aide à la recherche d'erreur.&lt;br&gt;
Comme l'outil a accès au contexte, il arrive très rapidement à trouver la source des erreurs, et les explique simplement avant de les corriger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Astuce&lt;/strong&gt; : demander à Amazon Q de relancer les tests à chaque fois qu'il corrige les erreurs. Ainsi il vérifie que tout est correct avant de vous rendre la main.&lt;br&gt;
Il arrive que la correction ne soit que partiellement bonne, voire incorrecte. Dans ce cas, je regarde le code qu'il a modifié (car sur ce point il est impressionnant) et je lui donne une proposition différente de correction. Il va prendre en compte la proposition et souvent proposer une correction améliorée en prenant en compte le contexte de l'application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation et tests
&lt;/h2&gt;

&lt;p&gt;Je dois avouer que c'est un grand plus pour moi.&lt;/p&gt;

&lt;p&gt;Amazon Q va me préparer un ensemble de tests intéressants, des rapports précis et je peux lui demander de rajouter d'autres tests si nécessaire.&lt;/p&gt;

&lt;p&gt;Dans notre cas, je suis resté assez simple :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Écris-moi des tests pour valider que les fonctions du jeu sont correctes. Je dois avoir un rapport complet, avec un résumé des résultats en début, puis le détail des tests et des erreurs trouvées. Si je te demande de corriger une erreur, ajoute un nouveau test pour s'assurer que celle-ci ne reviendra plus.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amazon Q me fournit un rapport sous ce format :&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25m3g8iwwkf1mx3ayw03.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25m3g8iwwkf1mx3ayw03.webp" alt="Amazon Q test report pour jeu R-Type" width="605" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ce que j'ai appris
&lt;/h2&gt;

&lt;p&gt;Nous sommes encore loin du résultat final, je vais continuer à faire évoluer ce projet.&lt;br&gt;
Nous avons des bases solides :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;une documentation à jour et accessible&lt;/li&gt;
&lt;li&gt;des tests sur plusieurs niveaux&lt;/li&gt;
&lt;li&gt;des scripts pour lancer l'application, la compiler et la déployer&lt;/li&gt;
&lt;li&gt;des templates pour créer de l'infrastructure, avec une gestion de plusieurs environnements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce résultat n'a demandé que peu d'efforts et de temps. Je me suis concentré sur les besoins, j'ai fourni à Amazon Q des prompts très simples, en lui laissant le temps de coder le tout.&lt;/p&gt;

&lt;p&gt;&lt;br&gt; Ce développement s'est donc fait juste avant de me faire un café, entre&lt;br&gt;
deux mails ou réunions. Cet assistant m'a permis d'être plus efficace, car j'ai&lt;br&gt;
pu faire cette preuve de concept tout en travaillant, entre autres sur la&lt;br&gt;
rédaction de ce post.&lt;/p&gt;

&lt;p&gt;Même avec une interaction limitée sur ce projet j'ai appris :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;savoir déléguer, organiser mes propos pour être bien compris&lt;/li&gt;
&lt;li&gt;me concentrer sur &lt;strong&gt;CE QUE JE VEUX&lt;/strong&gt; et non sur le &lt;strong&gt;COMMENT LE FAIRE&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;diviser les demandes en unités simples que l'on fera ensuite travailler ensemble&lt;/li&gt;
&lt;li&gt;avoir une démarche agile, basée sur les tests, avec des itérations courtes et rapides&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;J'ai été surpris par les performances de cet assistant et particulièrement par :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;la mise en place de bonnes pratiques et les propositions de mise en place d'améliorations de la sécurité ou des performances.&lt;/li&gt;
&lt;li&gt;la prise en considération du contexte, le fait de ne pas simplement faire ce que je demande au niveau du code, mais aussi de mettre à jour les tests et la documentation de son propre chef.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>jeux</category>
      <category>iagenerative</category>
      <category>amazonq</category>
    </item>
    <item>
      <title>AWS VPC centralisée ou VPC dans les comptes projets : Quand, Pourquoi et Comment ?</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:10:23 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-vpc-centralisee-ou-vpc-dans-les-comptes-projets-quand-pourquoi-et-comment--50k7</link>
      <guid>https://dev.to/aws-builders/aws-vpc-centralisee-ou-vpc-dans-les-comptes-projets-quand-pourquoi-et-comment--50k7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nx7925mfdrdr6sqzi0w.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nx7925mfdrdr6sqzi0w.webp" alt="AWS VPC centralisée ou VPC dans les comptes projets : Quand, Pourquoi et Comment ?" width="799" height="333"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Bien que le partage d'Amazon Virtual Private Cloud (&lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/" rel="noopener noreferrer"&gt;VPC&lt;/a&gt;) soit disponible depuis fin 2018, il est encore rare de le voir déployé dans les landing zones.&lt;/p&gt;

&lt;p&gt;Cette possibilité peut apporter de nombreux gains en termes d'organisation et de répartition des tâches entre les équipes, des économies non négligeables, et une implémentation réseau alignée avec le modèle opérationnel de l'entreprise.&lt;br&gt;
Nous allons voir ensemble les points qui vont pousser l'adoption de cette implémentation à la place d'une implémentation décentralisée, qui elle est le reflet d'une organisation plus orientée DevOps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les Challenges
&lt;/h2&gt;

&lt;p&gt;Les VPCs sont difficilement extensibles, et il est compliqué de réorganiser les ressources qui sont à l'intérieur. Il est donc nécessaire de choisir la bonne implémentation dès la mise en place de la landing zone.&lt;/p&gt;

&lt;p&gt;Il est également important de n'avoir aucun VPC avec un CIDR block (ensemble d'IP) identique, ce qui rendrait le routage complexe.&lt;/p&gt;

&lt;p&gt;Dans les grands groupes, une portion importante des &lt;a href="https://fr.wikipedia.org/wiki/R%C3%A9seau_priv%C3%A9" rel="noopener noreferrer"&gt;IP privées&lt;/a&gt; ont été consommées.&lt;br&gt;
Souvent un CIDR Block /16 est assigné à un cloud provider, ce qui nécessite une réflexion importante pour organiser les VPCs et les subnets.&lt;/p&gt;

&lt;p&gt;L'organisation de l'entreprise est aussi importante. La responsabilité du réseau peut être assumée par différentes équipes, et il est important que les politiques &lt;a href="https://docs.aws.amazon.com/iam/latest/userguide/" rel="noopener noreferrer"&gt;AWS Identity and Access Management (IAM)&lt;/a&gt; reflètent ces responsabilités.&lt;br&gt;
Pour faciliter ces règles IAM, une organisation des comptes AWS rigoureuse est nécessaire.&lt;/p&gt;

&lt;p&gt;La maîtrise des coûts et la sécurité sont les deux derniers domaines qui influencent l'organisation réseau.&lt;br&gt;
Comme nous le verrons plus loin, les liaisons réseaux ont un coût non négligeable et peuvent à l'échelle devenir un problème financier.&lt;/p&gt;

&lt;h2&gt;
  
  
  VPC par compte, le modèle par défaut
&lt;/h2&gt;

&lt;p&gt;Chaque compte AWS étant indépendant, nous pouvons donc aisément créer une infrastructure réseau indépendante.&lt;br&gt;
Un VPC par défaut est fourni dans chaque compte, je vous déconseille de l'utiliser dans votre landing zone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0ajah07nlsbs6fy419l.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0ajah07nlsbs6fy419l.webp" alt="VPC in an account" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il est donc aisé de créer les ressources réseau pour un projet lors de son déploiement. Nous avons un tout cohérent, et si nous devons terminer le projet, nous pourrons détruire toutes les ressources liées.&lt;br&gt;
C'est également ce que l'on retrouve sur de nombreux modèles de projet (blueprint). En créant tous les éléments, du réseau à l'application, on s'assure que tous les éléments seront conformes et fonctionnels.&lt;/p&gt;

&lt;p&gt;Ce modèle est également apprécié car il fait écho à la philosophie DevOps, où l'équipe projet est responsable de son périmètre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modèle centralisé
&lt;/h2&gt;

&lt;p&gt;Le but de ce modèle est d'éviter le morcellement de la partie réseau. Dans ce modèle, nous allons créer un nombre limité de VPC, qui se trouveront dans le compte AWS gérant le réseau.&lt;br&gt;
Il y aura au moins 2 VPCs, un pour la production et un pour la non-production. Cela permettra de gérer les flux entre ces 2 zones, et rassurera les équipes sécurité.&lt;br&gt;
Le modèle de sous-réseau (Subnets) sera le même que pour le modèle décentralisé, c'est la taille de ces subnets qui sera supérieure.&lt;br&gt;
Ces subnets seront ensuite partagés avec les comptes projets pour qu'ils puissent les utiliser.&lt;/p&gt;

&lt;p&gt;Ce modèle reflète le modèle opérationnel où les équipes réseau et sécurité sont responsables des fondations réseau. Les équipes projets ne sont qu'utilisatrices des ressources mises à disposition et vont créer les ressources projets dans les sous-réseaux fournis sans pouvoir modifier leur fonctionnement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6gk93o58j88wbxx0l3f.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6gk93o58j88wbxx0l3f.webp" alt="VPC Centralisée" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Critères de sélection
&lt;/h2&gt;

&lt;p&gt;Plusieurs critères entrent en compte, les plus impactants sont en premier :&lt;/p&gt;

&lt;h4&gt;
  
  
  Besoin de contrôle et de conformité lié à des contraintes légales
&lt;/h4&gt;

&lt;p&gt;Si la séparation des responsabilités est un prérequis et que le réseau est géré par une équipe spécialisée, un modèle centralisé est la solution à privilégier. Chaque projet aura son compte AWS, mais ils ne pourront pas créer de composants réseau au sein de ces comptes.&lt;/p&gt;

&lt;p&gt;Si la responsabilité du réseau est portée par le projet et non par une équipe centrale, un modèle décentralisé sera le meilleur choix.&lt;br&gt;
Il faudra néanmoins déployer des outils permettant de vérifier la conformité à l'échelle. Ces outils devront être capables de récupérer et d'agréger des données venant de nombreux comptes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Modèle opérationnel et responsabilité des équipes
&lt;/h4&gt;

&lt;p&gt;Les mêmes arguments que la partie précédente sont à utiliser pour choisir le modèle. La seule différence est que ce n'est pas un besoin externe qui impose le choix, mais le fonctionnement de l'entreprise.&lt;/p&gt;

&lt;p&gt;Il faut rester vigilant sur ce choix et penser à la transformation de l'entreprise en passant dans le cloud et la trajectoire pour les prochaines années.&lt;/p&gt;

&lt;p&gt;&lt;br&gt; Vous pouvez avoir un modèle centralisé car vous êtes en cours de&lt;br&gt;
migration depuis le on-premise, mais la stratégie d'entreprise est de devenir&lt;br&gt;
plus agile en laissant les projets porter leur responsabilité de bout en bout.&lt;br&gt;
Dans ce cas, un modèle décentralisé sera à privilégier, avec un accompagnement&lt;br&gt;
des équipes opérations / sécurité / réseau pour leur permettre d'évoluer et de&lt;br&gt;
s'inscrire dans le nouveau modèle opérationnel.&lt;/p&gt;

&lt;h4&gt;
  
  
  Maîtrise des coûts
&lt;/h4&gt;

&lt;p&gt;Un modèle décentralisé repose sur l'utilisation de la &lt;a href="https://docs.aws.amazon.com/vpc/latest/tgw/" rel="noopener noreferrer"&gt;Transit Gateway&lt;/a&gt; pour passer à l'échelle. Mais ce modèle a un coût non négligeable, lié au nombre de VPC qui vont être créés.&lt;/p&gt;

&lt;p&gt;Si la consommation de services AWS par VPC est faible (moins de 250$ par exemple, dans ce cas le réseau représente plus de 20% des dépenses), il est intéressant d'évaluer la possibilité de passer sur un modèle centralisé.&lt;/p&gt;

&lt;p&gt;Un modèle décentralisé permettra également de plus facilement répartir les coûts par projets. Les ressources n'étant pas mutualisées et un compte AWS n'étant lié qu'à un projet, la somme des consommations par projet sera donc aisée.&lt;/p&gt;

&lt;h4&gt;
  
  
  Maturité de la société sur AWS
&lt;/h4&gt;

&lt;p&gt;Si vous débutez sur AWS et que vous migrez depuis le on-premise, un modèle centralisé peut être rassurant car plus proche de ce que vous avez on-premise.&lt;/p&gt;

&lt;p&gt;Si vous êtes une société en création, que vous voulez être agile et que vous n'avez pas une équipe réseau dédiée, un modèle décentralisé vous apportera plus de souplesse. Cela vous permettra par exemple de proposer de nouveaux produits, et s'ils ne trouvent pas leur public, vous n'aurez qu'à détruire le ou les comptes AWS associés pour ne plus avoir de dépenses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Gestion des IPs
&lt;/h4&gt;

&lt;p&gt;Si la gestion des IPs est un enjeu, et que chaque IP compte car votre entreprise a consommé presque toutes les possibilités d'adressage IP privé, il est recommandé de passer sur un modèle centralisé qui permettra de ne perdre que très peu d'IPs.&lt;/p&gt;

&lt;p&gt;Si votre SI est d'une taille modeste, les 2 modèles peuvent être utilisés, ce sont d'autres critères qui guideront vos choix.&lt;/p&gt;

&lt;h4&gt;
  
  
  Isolation forte des projets
&lt;/h4&gt;

&lt;p&gt;Si vous devez isoler fortement des projets, par exemple si vous offrez une plateforme SaaS pour des clients, il est recommandé d'utiliser un modèle décentralisé. Les ressources réseau et projets de chaque client seront isolés dans un compte AWS, et vous pourrez également ajouter du filtrage réseau au niveau de la Transit Gateway.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mise en place de la VPC centralisée
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Organisation des VPCs
&lt;/h3&gt;

&lt;p&gt;Nous pouvons organiser les VPCs de différentes manières.&lt;/p&gt;

&lt;p&gt;La première solution, la plus simple, est de faire une VPC pour la production et une autre pour la non-production.&lt;br&gt;
L'avantage est que les IPs pour la production sont réservées, nous pouvons contrôler les flux entre les deux VPCs.&lt;/p&gt;

&lt;p&gt;La seconde solution est de faire un VPC par environnement. Cela permet un meilleur contrôle des flux est-ouest, et une garantie d'un nombre d'IP par environnement.&lt;/p&gt;



&lt;p&gt;Nous ajouterons une VPC supplémentaire pour les outils réseau comme les points de terminaison VPC (VPC Endpoints), la gestion DNS ou la gestion de l'Egress, quelle que soit la solution proposée.&lt;br&gt;
Ainsi, nous mutualisons les coûts des VPC Endpoints et de l'Egress.&lt;/p&gt;

&lt;p&gt;Les VPCs doivent être suffisamment grandes pour répondre à vos besoins en IP pour les années à venir.&lt;br&gt;
Il est possible d'étendre une VPC, mais cela reste une opération qui va ajouter de la complexité à votre landing zone.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exemple
&lt;/h4&gt;

&lt;p&gt;Vous avez 4 environnements : production, recette, intégration et développement.&lt;br&gt;
Vous avez à disposition un CIDR block 10.0.0.0/16&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Première solution&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un VPC de production 10.0.0.0/18&lt;/li&gt;
&lt;li&gt;un VPC de non-production (recette, intégration et développement) 10.0.128.0/17&lt;/li&gt;
&lt;li&gt;il reste 10.0.64.0/18 pour les VPCs réseau, sandbox, ou les services partagés&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VPC&lt;/th&gt;
&lt;th&gt;Subnet address&lt;/th&gt;
&lt;th&gt;Range of addresses&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;production&lt;/td&gt;
&lt;td&gt;10.0.0.0/18&lt;/td&gt;
&lt;td&gt;10.0.0.0 - 10.0.63.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;non-production&lt;/td&gt;
&lt;td&gt;10.0.128.0/17&lt;/td&gt;
&lt;td&gt;10.0.128.0 - 10.0.255.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autre&lt;/td&gt;
&lt;td&gt;10.0.64.0/18&lt;/td&gt;
&lt;td&gt;10.0.64.0 - 10.0.127.255&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Seconde solution&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un VPC de production : 10.0.0.0/19&lt;/li&gt;
&lt;li&gt;un VPC de recette (iso prod) : 10.0.64.0/18&lt;/li&gt;
&lt;li&gt;un VPC d'intégration : 10.0.128.0/19&lt;/li&gt;
&lt;li&gt;un VPC de développement : 10.0.160.0/19&lt;/li&gt;
&lt;li&gt;il reste 10.0.192.0/18 pour les VPCs réseau, sandbox, ou les services partagés&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VPC&lt;/th&gt;
&lt;th&gt;Subnet address&lt;/th&gt;
&lt;th&gt;Range of addresses&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;production&lt;/td&gt;
&lt;td&gt;10.0.0.0/18&lt;/td&gt;
&lt;td&gt;10.0.0.0 - 10.0.63.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recette&lt;/td&gt;
&lt;td&gt;10.0.64.0/18&lt;/td&gt;
&lt;td&gt;10.0.64.0 - 10.0.127.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;intégration&lt;/td&gt;
&lt;td&gt;10.0.128.0/19&lt;/td&gt;
&lt;td&gt;10.0.128.0 - 10.0.159.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;développement&lt;/td&gt;
&lt;td&gt;10.0.160.0/19&lt;/td&gt;
&lt;td&gt;10.0.160.0 - 10.0.191.255&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autre&lt;/td&gt;
&lt;td&gt;10.0.192.0/18&lt;/td&gt;
&lt;td&gt;10.0.192.0 - 10.0.255.255&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Partage des subnets
&lt;/h3&gt;

&lt;p&gt;Nous avons plusieures stratégies pour le partage des subnets.&lt;/p&gt;

&lt;h4&gt;
  
  
  1 - Centralisation des VPCs dans le compte réseau
&lt;/h4&gt;

&lt;p&gt;C'est le modèle le plus simple, la séparation en VPC projet est conservée, la différence est que les VPCs se trouvent dans le compte réseau.&lt;/p&gt;

&lt;p&gt;L'avantage de cette technique est qu'elle simplifie la gestion IAM pour le réseau, on s'assure ainsi que les projets ne pourront pas modifier les fondations mises en place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafxhzuj8pzo8nvhvjgva.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafxhzuj8pzo8nvhvjgva.webp" alt="Centralisation des VPCs dans le compte réseau" width="793" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2 - Un seul VPC, des subnets indépendants pour chaque compte
&lt;/h4&gt;

&lt;p&gt;Ce modèle assure une isolation stricte entre les comptes, car chaque subnet est lié à un seul compte AWS.&lt;br&gt;
Ainsi il n'y a pas de risque de manque d'IP venant d'un autre projet, les coûts d'interconnexions sont réduits car on a moins de VPCs.&lt;/p&gt;

&lt;p&gt;Pour assurer une isolation parfaite, il est recommandé d'ajouter des listes de contrôle d'accès réseau (NACL) aux sous-réseaux pour ne laisser passer que les flux venant de sous-réseaux légitimes.&lt;/p&gt;

&lt;p&gt;Cela ne facilite toujours pas suffisamment la gestion des adresses IP. Nous avons toujours des adresses IP utilisées dans chaque sous-réseau, et si nous n'avons plus d'adresses IP disponibles sur un sous-réseau, il faudra utiliser un nouveau sous-réseau pour étendre la plage d'adresses IP.&lt;/p&gt;

&lt;p&gt;Cela nécessite encore de trouver la ou les bonnes tailles de sous-réseaux pour les projets, afin de réduire le nombre d'adresses IP non utilisées.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibyo8mbkv8llo9rdpaml.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibyo8mbkv8llo9rdpaml.webp" alt="Un seul VPC, des subnets indépendants pour chaque compte" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3 - Un seul VPC, des sous-réseaux partagés entre tous les comptes d'un même environnement
&lt;/h4&gt;

&lt;p&gt;Dans cette solution, nous avons un petit nombre de sous-réseaux de grande taille partagés entre les comptes.&lt;br&gt;
L'isolation est en place par design, nous le verrons un peu plus bas, et avec ce modèle nous obtenons une zone de travail où aucune IP ne sera potentiellement inutilisée, et il n'est plus nécessaire de réfléchir longuement à la taille de chacun des sous-réseaux.&lt;/p&gt;

&lt;p&gt;Tout comme la solution précédente, le nombre d'interconnexions réseau est réduit au strict minimum pour maîtriser les coûts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4gokoxb3eva8nfcrg2c.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4gokoxb3eva8nfcrg2c.webp" alt="Un seul VPC, des subnets partagés entre tous les comptes d'un même environnement" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsabilité partagée
&lt;/h3&gt;

&lt;p&gt;Comme nous l'avons vu plus haut, le modèle de VPC doit refléter le modèle de responsabilité entre les équipes. AWS a fait le nécessaire au niveau des droits, pour que cette séparation soit claire.&lt;br&gt;
Source : &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-share-limitations.html" rel="noopener noreferrer"&gt;Responsibilities and permissions for owners and participants&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Responsabilité du compte qui partage
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Il est responsable de la &lt;strong&gt;création&lt;/strong&gt;, de la &lt;strong&gt;gestion&lt;/strong&gt; et de la &lt;strong&gt;suppression&lt;/strong&gt; des &lt;strong&gt;ressources associées à un VPC partagé&lt;/strong&gt; (sous-réseaux, tables de routage, passerelles NAT, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
  La liste complète est disponible dans la documentation, et l'on peut vérifier&lt;br&gt;
  que ce ne sont que des composants de réseau, sécurité et routage qui peuvent&lt;br&gt;
  être gérés.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;il &lt;strong&gt;ne peut pas modifier les interfaces réseau&lt;/strong&gt; appartenant aux participants (attacher, détacher...).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
  Les interfaces sont visibles dans le compte qui partage, ce qui a du sens car&lt;br&gt;
  les interfaces utilisent les IPs du compte. Les informations sont limitées, on&lt;br&gt;
  ne sait rien sur la ressource liée.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;il peut &lt;strong&gt;visualiser les &lt;a href="https://docs.aws.amazon.com/fr_fr/vpc/latest/userguide/vpc-security-groups.html" rel="noopener noreferrer"&gt;groupes de sécurité&lt;/a&gt;&lt;/strong&gt; créés par les participants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
  Le principe d'observabilité est respecté, et les responsables du réseau et de&lt;br&gt;
  la sécurité peuvent examiner facilement ce qui est implémenté. Dans l'exemple&lt;br&gt;
  ci-dessous, nous pouvons voir des groupes de sécurité liés à d'autres comptes&lt;br&gt;
  avec la mention &lt;strong&gt;shared&lt;/strong&gt; entre parenthèses.&lt;br&gt;
  &lt;br&gt;&lt;br&gt;
  Exemple :&lt;br&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j9tshdmuqkpsmdaj8i.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2j9tshdmuqkpsmdaj8i.webp" alt="Groupe de sécurité" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;il peut &lt;strong&gt;attacher une passerelle de transit&lt;/strong&gt; à un sous-réseau VPC partagé.
 Le principe de responsabilité est bien respecté, et cela évite des
dérives de sécurité (cartographie des flux) et financières (prix de
l'attachement, coûts de trafic)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Responsabilité des comptes qui utilisent le partage
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;ils sont &lt;strong&gt;responsables des ressources VPC dont ils sont propriétaires&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Tout est dit, on respecte bien le modèle de responsabilité partagée&lt;br&gt;
  entre le compte qui partage et les comptes qui utilisent les sous-réseaux&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ils ne peuvent &lt;strong&gt;créer qu'un ensemble limité de ressources VPC&lt;/strong&gt; : groupes de sécurité, journaux de flux VPC (sur leurs interfaces réseau).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Les &lt;strong&gt;ressources VPC créées&lt;/strong&gt; par un participant sont &lt;strong&gt;comptabilisées dans les quotas VPC du compte participant&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Les participants ne peuvent pas &lt;strong&gt;créer, attacher ni supprimer de passerelles Internet&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Cela nous assure qu'il n'y aura pas d'exposition publique incontrôlée.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants &lt;strong&gt;ne peuvent pas créer ni supprimer de NAT Gateway&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; On évite ainsi des coûts non maîtrisés (35$ par mois). Ce sont des&lt;br&gt;
  éléments de routage que les équipes réseaux doivent mettre en place, que les&lt;br&gt;
  NAT Gateway soient privées ou publiques. Les équipes projet ne sont&lt;br&gt;
  qu'utilisatrices de ces services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants ne peuvent pas &lt;strong&gt;créer, supprimer ni remplacer&lt;/strong&gt; de listes de contrôle d'accès réseau (&lt;strong&gt;NACL&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; La sécurité du réseau est la responsabilité des équipes réseau et&lt;br&gt;
  sécurité. Personne dans le compte participant ne pourra unilatéralement&lt;br&gt;
  modifier des règles de filtrage réseau.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants peuvent &lt;strong&gt;visualiser les NACL&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Le filtrage mis en place peut être visualisé par l'équipe projet&lt;br&gt;
  (transparence) et peut ainsi permettre de comprendre pourquoi certains&lt;br&gt;
  composants ne peuvent pas communiquer ensemble. Cela évite des frustrations et&lt;br&gt;
  peut faciliter le travail des équipes réseau qui pourront avoir des&lt;br&gt;
  indications claires des équipes projet.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants ne peuvent pas travailler sur des tables de routage (par exemple, &lt;strong&gt;créer, supprimer ou associer des tables de routage&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Tous les éléments réseau sont bien gérés pour que le partage de&lt;br&gt;
  responsabilité soit respecté par défaut.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants &lt;strong&gt;ne peuvent pas utiliser le groupe de sécurité par défaut du VPC&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Ce n'est pas une bonne pratique d'utiliser le groupe de sécurité par&lt;br&gt;
  défaut d'un VPC.&lt;br&gt;
  &lt;br&gt; La bonne pratique est de laisser ce groupe de sécurité sans règle, ce&lt;br&gt;
  qui bloque tout le trafic entrant et sortant. Donc ne pas pouvoir utiliser ce&lt;br&gt;
  groupe de sécurité ne posera pas de problème.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les participants &lt;strong&gt;ne peuvent pas utiliser de groupes de sécurité qui appartiennent au propriétaire du VPC ou à d'autres participants&lt;/strong&gt;, à moins que le groupe de sécurité ne soit partagé avec eux.
 Les règles des groupes de sécurité peuvent référencer un groupe de
sécurité d'un autre compte. Ce qui permet de gérer via des noms les flux entre
les applications. Il est nécessaire d'interdire l'utilisation d'un groupe de
sécurité extérieur au compte car les règles liées à celui-ci pourraient être
changées sans que le compte qui l'utilise soit informé.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Répartition des coûts
&lt;/h3&gt;

&lt;p&gt;Dans un VPC partagé, chaque participant paie ses ressources applicatives. Ils paient également les frais de transfert de données entre zones de disponibilité, via les passerelles Internet et les passerelles AWS &lt;a href="https://docs.aws.amazon.com//directconnect/latest/userguide/" rel="noopener noreferrer"&gt;Direct Connect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Les propriétaires de VPC paient des frais horaires ainsi que des frais de traitement et de transfert de données via les passerelles NAT, la Transit Gateway, &lt;a href="https://docs.aws.amazon.com//vpc/latest/privatelink/" rel="noopener noreferrer"&gt;PrivateLink&lt;/a&gt; et les points de terminaison VPC.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Les adresses IPv4 publiques utilisées dans les VPC partagés sont facturées aux&lt;br&gt;
propriétaires de VPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limites et points d'attention
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Les tags des groupes de sécurité créés dans un compte ne sont pas visibles dans les autres comptes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt; Nous ne pouvons pas profiter nativement des informations originales.&lt;br&gt;
  Nous pouvons recréer de nouveaux tags sur ces groupes de sécurité et leurs&lt;br&gt;
  règles dans le compte utilisant le sous-réseau via une&lt;br&gt;
  &lt;a href="https://docs.aws.amazon.com//lambda/latest/dg/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; par exemple.&lt;br&gt;
  &lt;br&gt; Exemple : - dans le compte utilisant un sous-réseau partagé :&lt;br&gt;
  &lt;br&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5dfcvdsotw6gi0mobik.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5dfcvdsotw6gi0mobik.webp" alt="Groupe de sécurité 2" width="800" height="455"&gt;&lt;/a&gt; - dans le&lt;br&gt;
  compte qui partage le sous-réseau :&lt;br&gt;
  &lt;br&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojs3a7bfz3wnmdj13k9p.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojs3a7bfz3wnmdj13k9p.webp" alt="Groupe de sécurité 3" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modèle centralisé et zones de disponibilité
&lt;/h3&gt;

&lt;p&gt;Dans le modèle centralisé, comme le trafic ne quitte pas le VPC, vous ne payez pas de frais de réseau supplémentaires, mais uniquement les éventuels frais de réseau inter-zones.&lt;/p&gt;

&lt;p&gt;Il est important de noter que tous les comptes AWS disposent d'un mappage de zones de disponibilité aléatoire. Ainsi, la zone de disponibilité A du compte A peut être la zone de disponibilité B du compte B. Lors de l'utilisation d'un VPC partagé, il est important d'en tenir compte pour limiter les frais de réseau inter-zones. Une bonne utilisation des tags peut réduire ces coûts en nommant de manière claire les sous-réseaux en s'appuyant sur l'ID de zone de disponibilité.&lt;/p&gt;

&lt;h3&gt;
  
  
  Que se passe-t-il si le partage est coupé ?
&lt;/h3&gt;

&lt;p&gt;Le propriétaire peut à tout moment annuler le partage d'un sous-réseau partagé. Une fois le partage d'un sous-réseau annulé, les règles suivantes s'appliquent :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les ressources existantes des participants continuent de s'exécuter dans le sous-réseau.&lt;/li&gt;
&lt;li&gt;Les participants ne peuvent plus créer de ressources dans le sous-réseau.&lt;/li&gt;
&lt;li&gt;Les participants peuvent modifier, décrire et supprimer leurs ressources.&lt;/li&gt;
&lt;li&gt;Si des participants disposent encore de ressources dans le sous-réseau, le propriétaire ne peut pas supprimer le sous-réseau partagé ni le VPC du sous-réseau partagé.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pour conclure
&lt;/h2&gt;

&lt;p&gt;Ces deux modèles sont complémentaires et répondent chacun à des besoins spécifiques.&lt;/p&gt;

&lt;p&gt;Vous pouvez également appliquer chacun de ces modèles à une partie de votre système d'information.&lt;/p&gt;

&lt;p&gt;&lt;br&gt; Si vous avez par exemple des applications que vous voulez déplacer à&lt;br&gt;
partir du on-premise et que vous ne pouvez pas transformer, vous pouvez les&lt;br&gt;
héberger sur un VPC centralisé. Pour les nouveaux projets, vous pouvez utiliser&lt;br&gt;
un modèle décentralisé qui apporte plus de souplesse aux équipes de&lt;br&gt;
développement.&lt;/p&gt;

&lt;p&gt;Il est important de choisir le modèle qui correspond à vos besoins (légaux, opérationnels, ...), qui soit efficace et aligné avec votre savoir-faire, plutôt que d'utiliser un modèle à la mode qui, au final, vous amènera à des coûts élevés et à des opérations plus complexes et coûteuses.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>securite</category>
      <category>gouvernance</category>
      <category>vpc</category>
    </item>
    <item>
      <title>AWS CloudFront VPC Origin : Sécurisez et Optimisez vos sites web publics</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Tue, 11 Aug 2026 09:23:52 +0000</pubDate>
      <link>https://dev.to/sylvainbruas/aws-cloudfront-vpc-origin-securisez-et-optimisez-vos-sites-web-publics-5eii</link>
      <guid>https://dev.to/sylvainbruas/aws-cloudfront-vpc-origin-securisez-et-optimisez-vos-sites-web-publics-5eii</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon3uwmrj289qhl66ay3l.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon3uwmrj289qhl66ay3l.webp" alt="AWS CloudFront Amazon Virtual Private Cloud (VPC) Origin : Sécurisez et Optimisez vos sites web publics" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Amazon &lt;a href="https://docs.aws.amazon.com//cloudfront" rel="noopener noreferrer"&gt;CloudFront&lt;/a&gt; est l'un de mes services AWS préférés. Grâce à cet&lt;br&gt;
outil, nous pouvons exposer des sites sur Internet, qu'ils soient&lt;br&gt;
statiques ou dynamiques, hébergés ou non sur AWS, avec une sécurité renforcée.&lt;/p&gt;

&lt;p&gt;Grâce à son déploiement au plus près de l'utilisateur, depuis 2008 ce&lt;br&gt;
service permet de distribuer le contenu avec les meilleures&lt;br&gt;
performances.&lt;/p&gt;

&lt;p&gt;Pour mettre du contenu à disposition de CloudFront, nous avons 2&lt;br&gt;
possibilités principales :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Utiliser &lt;a href="https://docs.aws.amazon.com//s3" rel="noopener noreferrer"&gt;Amazon Simple Storage Service (S3)&lt;/a&gt; ou &lt;a href="https://docs.aws.amazon.com//lambda" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; par exemple en utilisant&lt;br&gt;
les &lt;strong&gt;Origin Access Control&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Utiliser un équilibreur de charge (Load Balancer) ou une instance&lt;br&gt;
publique.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm88lsswpwdxfwnfbcij.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm88lsswpwdxfwnfbcij.webp" alt="Exposition du contenu d'un bucket S3 via CloudFront" width="469" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsylvain.bruas.fr%2Fstatic%2F2025%2F02%2Fimage2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsylvain.bruas.fr%2Fstatic%2F2025%2F02%2Fimage2.webp" alt="Exposition d'un service web hébergé sur une instance [Amazon Elastic Compute Cloud (EC2)](https://docs.aws.amazon.com//ec2) via CloudFront" width="629" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dans la suite de l'article, nous allons nous concentrer sur le cas de l'équilibreur de charge public.&lt;/p&gt;

&lt;p&gt;Les groupes de sécurité (Security Groups) doivent être bien configurés pour ne permettre l'accès que depuis CloudFront. Des protections supplémentaires peuvent être mises en place comme un &lt;a href="https://docs.aws.amazon.com//waf" rel="noopener noreferrer"&gt;AWS Web Application Firewall (WAF)&lt;/a&gt; par exemple, qui offre une protection avancée contre les attaques web, mais ceci engendre des coûts additionnels.&lt;/p&gt;

&lt;p&gt;Il est possible également d'utiliser un header pour identifier notre distribution CloudFront, mais cette technique ne protège pas contre les tentatives de connexions. Elles sont arrêtées au plus tôt au niveau de l'ALB, mais elles polluent les logs et peuvent impacter les performances.&lt;/p&gt;

&lt;p&gt;Voici un exemple de règle de groupe de sécurité permettant un accès uniquement via CloudFront en HTTPS :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;td&gt;pl-4fa04526 (com.amazonaws.global.cloudfront.origin-facing)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ces points d'accès peuvent être découverts via un scan d'IP systématique ou en&lt;br&gt;
listant les sous-domaines d'une entrée DNS, et être la cible d'attaques&lt;br&gt;
malveillantes (DDoS, DoS, tentative d'exploitation de faille etc.). Si l'instance&lt;br&gt;
EC2 derrière le load balancer a un serveur web avec une faille de&lt;br&gt;
sécurité critique et que le groupe de sécurité en amont permet du trafic ne&lt;br&gt;
venant pas de CloudFront, votre instance et par extension votre &lt;a href="https://docs.aws.amazon.com//vpc" rel="noopener noreferrer"&gt;VPC&lt;/a&gt;&lt;br&gt;
pourraient être compromis.&lt;/p&gt;

&lt;p&gt;Exemple de règle trop permissive :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;strong&gt;0.0.0.0/0&lt;/strong&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvkqrub19sezqehhm55a.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvkqrub19sezqehhm55a.webp" alt="Une source cloudfront qui se fait attaquer " width="647" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le meilleur moyen d'éviter cela est de garder la source de CloudFront&lt;br&gt;
privée, ce qui est possible depuis le 20 novembre 2024 avec les origines&lt;br&gt;
VPC sécurisées.&lt;br&gt;
Nous pouvons ainsi enlever la partie publique de nos VPCs, et nous&lt;br&gt;
pouvons également bloquer l'accès public aux VPCs de manière systématique&lt;br&gt;
( &lt;a href="https://docs.aws.amazon.com/fr_fr/vpc/latest/userguide/security-vpc-bpa.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/fr_fr/vpc/latest/userguide/security-vpc-bpa.html&lt;/a&gt; ).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcsx4na8xtexwi9xr9k1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcsx4na8xtexwi9xr9k1.webp" alt="Utilisation de CloudFront VPC Origin pour utiliser un load balancer privé comme source" width="649" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Avec cette architecture, nous réduisons également le besoin d'IPs privées&lt;br&gt;
par VPC en enlevant les subnets publics, ce qui est un premier point&lt;br&gt;
intéressant pour certaines compagnies où l'adressage privé est un sujet&lt;br&gt;
critique.&lt;/p&gt;

&lt;p&gt;Nous remplaçons le load balancer public par un privé, ce qui réduit la&lt;br&gt;
surface d'exposition de manière significative. S'il y avait déjà un load balancer privé qui&lt;br&gt;
exposait ce service, nous faisons donc une petite économie en enlevant&lt;br&gt;
un composant redondant.&lt;/p&gt;

&lt;p&gt;Une question demeure. En modifiant cette architecture, est-ce que nous&lt;br&gt;
modifions les performances de notre service ?&lt;br&gt;
Nous allons le vérifier en mettant en place une page Nginx sur une instance EC2 t3.micro à&lt;br&gt;
Singapour, et en testant les performances à partir de nos locaux (Lyon -&lt;br&gt;
France) ainsi que d'une session &lt;a href="https://docs.aws.amazon.com//cloudshell" rel="noopener noreferrer"&gt;CloudShell&lt;/a&gt; se trouvant en Irlande. Ce&lt;br&gt;
serveur Nginx sera exposé par un Load Balancer public et également via&lt;br&gt;
une VPC origin sur CloudFront.&lt;/p&gt;

&lt;p&gt;Dans un premier temps, nous n'activerons pas le cache en périphérie pour&lt;br&gt;
avoir des résultats objectifs (Si nous l'activions, le contenu ne serait&lt;br&gt;
plus récupéré sur le serveur Nginx à Singapour, mais sur l'edge&lt;br&gt;
CloudFront le plus proche contenant une copie). Nous ferons une dernière&lt;br&gt;
série de tests avec le cache activé, pour montrer l'efficacité d'un cache&lt;br&gt;
CloudFront bien configuré avec TTL standard quand on accède à des données qui sont très&lt;br&gt;
éloignées.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d2vlscb1aha1axdrs38.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d2vlscb1aha1axdrs38.webp" alt="Différentes requêtes pour récupérer le contenu" width="481" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nous allons donc effectuer 10 appels curl successifs et synchronisés à la suite pour avoir quelques&lt;br&gt;
statistiques intéressantes et fiables (Moyenne, Max, P90, Latence...).&lt;/p&gt;

&lt;p&gt;Voici le résultat détaillé de nos tests :&lt;/p&gt;

&lt;p&gt;Temps total (mesures complètes)&lt;br&gt;
| | Req1 | Req2 | Req3 | Req4 | Req5 | Req6 | Req7 | Req8 | Req9 | Req10 |&lt;br&gt;
| :--------------- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- | :----------- |&lt;br&gt;
| Irlande CloudFront | &lt;span&gt;0.394960s&lt;/span&gt; | 0.191579s | 0.194875s | &lt;span&gt;0.189899s&lt;/span&gt; | 0.191891s | 0.207810s | 0.193402s | 0.205370s | 0.197298s | 0.368063s |&lt;br&gt;
| Irlande ALB | 0.364543s | &lt;span&gt;0.367283s&lt;/span&gt; | 0.363094s | 0.366604s | &lt;span&gt;0.359450s&lt;/span&gt; | 0.362647s | 0.361881s | 0.365909s | 0.365682s | 0.365236s |&lt;br&gt;
| Lyon CloudFront | &lt;span&gt;0.407051s&lt;/span&gt; | 0.211910s | 0.238359s | 0.201906s | 0.369832s | &lt;span&gt;0.201490s&lt;/span&gt; | 0.206589s | 0.218557s | 0.542900s | 0.202360s |&lt;br&gt;
| Lyon ALB | &lt;span&gt;0.361772s&lt;/span&gt; | 0.322014s | 0.322883s | 0.317526s | &lt;span&gt;0.315286s&lt;/span&gt; | 0.317379s | 0.318128s | 0.316579s | 0.321974s | 0.324912s |&lt;br&gt;
| Lyon CloudFront + cache | &lt;span&gt;0.442350s&lt;/span&gt; | 0.043860s | 0.034697s | 0.043316s | 0.035482s | 0.041478s | 0.046235s | 0.033241s | 0.036595s | &lt;span&gt;0.029393s&lt;/span&gt; |&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Moyenne (sec)&lt;/th&gt;
&lt;th&gt;Plus longue (sec)&lt;/th&gt;
&lt;th&gt;Plus rapide (sec)&lt;/th&gt;
&lt;th&gt;P90 (percentile)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Irlande CloudFront&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.2335147s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;0.39496s&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.189899s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.21557633s&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Irlande ALB&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.3642329s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;0.367283s&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.35945s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.363894s&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lyon CloudFront&lt;/td&gt;
&lt;td&gt;0.2800954s&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.5429s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;0.20149s&lt;/td&gt;
&lt;td&gt;0.25089489s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lyon ALB&lt;/td&gt;
&lt;td&gt;0.3238453s&lt;/td&gt;
&lt;td&gt;&lt;span&gt;0.361772s&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;0.315286s&lt;/td&gt;
&lt;td&gt;0.31963122s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lyon CloudFront + cache&lt;/td&gt;
&lt;td&gt;0.0786647s&lt;/td&gt;
&lt;td&gt;0.44235s&lt;/td&gt;
&lt;td&gt;0.029393s&lt;/td&gt;
&lt;td&gt;0.03825522s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Comme on peut le voir, les performances sont meilleures en passant par&lt;br&gt;
CloudFront, ce qui s'explique aisément par le fait que la requête qui&lt;br&gt;
arrive sur CloudFront au plus près de l'utilisateur est ensuite envoyée&lt;br&gt;
via les backbones AWS vers la bonne ressource (chemin 1-2-3 et 21-22-23)&lt;br&gt;
sur le schéma suivant, optimisant ainsi le temps de latence global.\&lt;br&gt;
\&lt;br&gt;
Dans le cas de l'ALB, on effectue une résolution DNS, puis on passe par&lt;br&gt;
internet pour joindre la ressource (chemin 10-11 et 31-32). Nous passons&lt;br&gt;
par des ressources publiques et par plusieurs relais que nous ne&lt;br&gt;
maîtrisons pas, ce qui allonge les délais de réponses et peut introduire&lt;br&gt;
une variabilité importante.&lt;/p&gt;

&lt;p&gt;Comme on peut le voir dans les résultats, utiliser le cache CloudFront à&lt;br&gt;
la périphérie est la solution la plus performante, ce qui n'est pas une&lt;br&gt;
surprise étant donné que le trajet est beaucoup plus court (chemin 1-2&lt;br&gt;
seulement) et bénéficie de l'infrastructure optimisée d'AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p2bfa9ishyvhaojrsui.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p2bfa9ishyvhaojrsui.webp" alt="Différents chemins utilisé par nos requêtes pour récuprer les données" width="800" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La solution via CloudFront et VPC Origin n'est donc pas seulement plus&lt;br&gt;
sécurisée, mais aussi plus performante qu'une exposition via un ALB, grâce&lt;br&gt;
à la mise en cache globale.&lt;/p&gt;

&lt;p&gt;Cette solution est très efficace pour les sites Internet ou&lt;br&gt;
l'exposition de contenu de taille importante. Si vous exposez une API&lt;br&gt;
via votre ALB, cette solution peut néanmoins devenir coûteuse. Le modèle&lt;br&gt;
de facturation de CloudFront étant basé sur les données sortantes ET sur&lt;br&gt;
le nombre de requêtes. Dans le cas d'une API, il y a de très nombreuses&lt;br&gt;
petites requêtes, ce qui peut rendre l'exposition via CloudFront plus&lt;br&gt;
coûteuse que via un ALB classique.&lt;/p&gt;

&lt;p&gt;On peut donc dire que les VPC Origins pour CloudFront apportent une&lt;br&gt;
nouvelle façon d'exposer le contenu, en ajoutant une seconde couche de&lt;br&gt;
protection contre les mauvaises manipulations et les attaques externes. Même si vous définissez&lt;br&gt;
une règle en 0.0.0.0/0 pour le HTTP(S) dans votre Security Group, vos&lt;br&gt;
ressources étant en privé, elles resteront inaccessibles via Internet.&lt;br&gt;
Si vous n'avez pas encore ajouté CloudFront en première ligne de votre&lt;br&gt;
exposition Internet, je vous engage à le faire rapidement. Vous pourrez&lt;br&gt;
ainsi profiter de performances réseau accrues et d'une sécurité renforcée.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>securite</category>
      <category>gouvernance</category>
      <category>vpc</category>
    </item>
    <item>
      <title>AWS re:Invent 2025 : MCP Server Open Source pour la Planification</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Tue, 11 Aug 2026 09:23:16 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-reinvent-2025-mcp-server-open-source-pour-la-planification-482</link>
      <guid>https://dev.to/aws-builders/aws-reinvent-2025-mcp-server-open-source-pour-la-planification-482</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ig94e5pyj41z801kv3n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ig94e5pyj41z801kv3n.webp" alt="AWS re:Invent 2025 : MCP Server Open Source pour la Planification" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Le Model Context Protocol, une Révolution pour l'IA
&lt;/h2&gt;

&lt;p&gt;Le Model Context Protocol (MCP) représente une avancée majeure dans l'écosystème de l'intelligence artificielle. Développé par Anthropic, MCP standardise la façon dont les modèles d'IA accèdent et interagissent avec des sources de données externes. Contrairement aux approches traditionnelles où chaque intégration nécessite un développement spécifique, MCP propose un protocole unifié qui permet aux modèles d'IA de découvrir et d'utiliser automatiquement des outils externes.&lt;/p&gt;

&lt;p&gt;L'intérêt principal de MCP réside dans sa capacité à étendre les capacités des modèles d'IA au-delà de leurs connaissances pré-entraînées. Un serveur MCP expose des "outils" que l'IA peut invoquer dynamiquement selon le contexte de la conversation. Cette approche ouvre des possibilités infinies : accès à des bases de données en temps réel, intégration avec des APIs externes, manipulation de fichiers, et bien plus encore.&lt;/p&gt;

&lt;p&gt;Dans cet article, je partage mon retour d'expérience sur le développement d'un serveur MCP pour AWS re:Invent 2025, mon premier projet open source de cette envergure. Ce projet illustre parfaitement les défis et opportunités du développement MCP, tout en démontrant comment (Kiro)[&lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;https://kiro.dev/&lt;/a&gt;] peut considérablement accélérer le processus de développement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le Défi : Gérer la Complexité d'AWS re:Invent
&lt;/h2&gt;

&lt;p&gt;AWS re:Invent est l'une des conférences technologiques les plus importantes au monde, avec plus de 2200 sessions réparties sur 5 jours dans plusieurs hôtels de Las Vegas. Pour un participant, naviguer dans cette masse d'informations représente un défi considérable :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Volume de données&lt;/strong&gt; : 2200 sessions avec des métadonnées complexes (niveaux, services AWS, speakers, lieux)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sources multiples&lt;/strong&gt; : API officielle, flux RSS des mises à jour, agenda AWS des événements spéciaux&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Besoins personnalisés&lt;/strong&gt; : Gestion d'événements personnels, listes de favoris, export calendrier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contraintes temps réel&lt;/strong&gt; : Synchronisation continue des données, cache intelligent&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reinvent-planner.cloud par Raphael Manke
&lt;/h3&gt;

&lt;p&gt;Ce projet s'appuie sur l'excellent travail de &lt;strong&gt;Raphael Manke&lt;/strong&gt; et son site &lt;a href="https://reinvent-planner.cloud/" rel="noopener noreferrer"&gt;reinvent-planner.cloud&lt;/a&gt;, qui constitue la source de données principale de notre serveur MCP. Raphael a créé une API robuste et bien documentée qui agrège les données officielles d'AWS re:Invent, les enrichit avec des métadonnées utiles, et les expose via une interface REST moderne.&lt;/p&gt;

&lt;p&gt;L'API de reinvent-planner.cloud fournit :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Catalogue complet&lt;/strong&gt; : 2200+ sessions avec détails techniques et mises à jour journalières&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flux RSS&lt;/strong&gt; : Notifications des nouvelles sessions et modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Métadonnées enrichies&lt;/strong&gt; : Niveaux de difficulté, services AWS, topics, speakers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtrage avancé&lt;/strong&gt; : Par lieu, jour, niveau, service, domaine d'intérêt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sans cette infrastructure de qualité, développer un serveur MCP aussi complet aurait nécessité un effort considérable de scraping et de normalisation des données. Le travail de Raphael illustre parfaitement l'importance de l'écosystème open source dans la création de solutions innovantes.&lt;/p&gt;

&lt;p&gt;L'objectif était de créer un serveur MCP capable de transformer cette complexité en une interface simple et intuitive pour les modèles d'IA, tout en s'appuyant sur cette base de données fiable et maintenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Technique : Une Approche en Couches
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vue d'Ensemble du Système
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbdfso00vwlvbtor6xqdu.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbdfso00vwlvbtor6xqdu.webp" alt="Vue d'Ensemble du Système MCP re:Invent" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture en Couches Détaillée
&lt;/h3&gt;

&lt;p&gt;L'architecture suit un modèle en trois couches bien défini :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gse7tzn3ie8a9a07gju.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gse7tzn3ie8a9a07gju.webp" alt="Architecture en Trois Couches" width="703" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Locale vs Web : Choix et Implications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Exécution Locale : Avantages et Contraintes
&lt;/h3&gt;

&lt;p&gt;Le serveur MCP re:Invent fonctionne entièrement en local sur la machine de l'utilisateur, une approche qui présente des avantages significatifs mais aussi des limitations :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avantages de l'approche locale :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimale&lt;/strong&gt; : Pas de latence réseau pour les requêtes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Données privées&lt;/strong&gt; : Événements personnels et favoris restent sur la machine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disponibilité offline&lt;/strong&gt; : Fonctionnement même sans connexion internet (cache) ou dans les transports (train, avion ...)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coût zéro&lt;/strong&gt; : Pas d'infrastructure serveur à maintenir&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicité de déploiement&lt;/strong&gt; : Installation directe via script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Contraintes identifiées :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Installation requise&lt;/strong&gt; : Chaque utilisateur doit configurer l'environnement Python&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance individuelle&lt;/strong&gt; : Mises à jour à déployer sur chaque poste&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration Locale Actuelle
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reinvent-planner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/venv/bin/python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./server.py"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PYTHONPATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/project"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cette configuration lance un processus Python local qui communique avec Kiro via STDIO, créant une expérience transparente pour l'utilisateur.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composants Clés et Défis Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Gestionnaire de Cache Intelligent
&lt;/h3&gt;

&lt;p&gt;Le cache représente un défi majeur avec 2200 sessions à gérer. Il est indispensable d'avoir le moins de pression possible sur les sources de données, ceci est possible car les données ne sont pas rafraichies très fréquemment. L'approche adoptée combine cache mémoire et persistance SQLite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Défis rencontrés :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gestion de la cohérence entre cache mémoire et base de données&lt;/li&gt;
&lt;li&gt;Optimisation des performances avec de gros volumes&lt;/li&gt;
&lt;li&gt;Stratégie de fallback en cas d'indisponibilité API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Moteur de Recherche Multi-Critères
&lt;/h3&gt;

&lt;p&gt;Le moteur de recherche doit gérer 8 types de filtres différents avec des performances optimales :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Exemple de recherche complexe
&lt;/span&gt;&lt;span class="nf"&gt;search_sessions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI machine learning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tuesday&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;venue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Venetian&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SageMaker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bonne pratique :&lt;/strong&gt; Utilisation d'index SQLite optimisés et requêtes préparées pour maintenir des temps de réponse &amp;lt; 2 secondes même avec 2200+ résultats.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Synchronisateur Multi-Sources
&lt;/h3&gt;

&lt;p&gt;La synchronisation de trois sources de données hétérogènes présente des défis uniques :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2s83kggyhtd9632ho5hd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2s83kggyhtd9632ho5hd.webp" alt="Synchronisation des Sources de Données" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  L'Apport de Kiro dans le Développement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Accélération du Processus de Spécification
&lt;/h3&gt;

&lt;p&gt;Kiro a amélioré mon approche de ce développement en me soutenant avec une mise en forme structuré de mes idées et spécifications. j'ai ensuite pu dérouler les phases suivantes (Design puis Taches) pour implémenter cette solution. J'ai pu également tester facilement les évolutions de ce projet en connectant Kiro avec le serveur MCP que j'étais en train de concevoir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration de Kiro pour le Serveur MCP
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation et Configuration Initiale
&lt;/h3&gt;

&lt;p&gt;La mise en place du serveur MCP dans Kiro est assez simple :&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Installation du Serveur MCP
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cloner le projet&lt;/span&gt;
git clone https://github.com/sylvainbruas/reinvent-planner
&lt;span class="nb"&gt;cd &lt;/span&gt;reinvent-planner

&lt;span class="c"&gt;# Installation automatique&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x install.sh
./install.sh

&lt;span class="c"&gt;# Ou installation manuelle&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Configuration MCP dans Kiro
&lt;/h4&gt;

&lt;p&gt;Créer ou modifier le fichier &lt;strong&gt;.kiro/settings/mcp.json&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reinvent-planner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./reinvent-planner/venv/bin/python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./reinvent-planner/server.py"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./reinvent-planner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"PYTHONPATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./reinvent-planner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"LOG_LEVEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INFO"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"autoApprove"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"search_sessions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_session_details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"list_available_filters"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_schedule_by_day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_rss_updates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sync_rss_feed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_aws_events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sync_aws_events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sync_all_data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_sync_history"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"add_personal_event"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_personal_events"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"delete_personal_event"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"add_session_to_favorites"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"get_favorite_sessions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"remove_session_from_favorites"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"create_favorite_list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"export_schedule_to_ical"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Vérification de la Connexion
&lt;/h4&gt;

&lt;p&gt;Une fois configuré, Kiro affiche le serveur MCP dans le panneau des outils disponibles :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ reinvent-planner (18 outils disponibles)
   📊 Sessions: search_sessions, get_session_details, list_available_filters, get_schedule_by_day
   🔄 Sync: get_rss_updates, sync_rss_feed, get_aws_events, sync_aws_events, sync_all_data, get_sync_history
   👤 Personnel: add_personal_event, get_personal_events, delete_personal_event
   ⭐ Favoris: add_session_to_favorites, get_favorite_sessions, remove_session_from_favorites, create_favorite_list
   📤 Export: export_schedule_to_ical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exemples de Requêtes Complexes avec Kiro
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Requêtes Simples - Utilisation du Serveur MCP Seul
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Recherche et Planification de Base
&lt;/h4&gt;

&lt;p&gt;Trouve-moi toutes les sessions sur l'intelligence artificielle niveau 300 ou plus au Venetian mardi, et ajoute les 3 plus intéressantes à ma liste plan_a&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outils MCP utilisés :&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;search_sessions(query="intelligence artificielle", venue="Venetian", day="Tuesday", level=300)&lt;/li&gt;
&lt;li&gt;add_session_to_favorites(session_id="...", list_name="plan_a", priority=1)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  2. Gestion d'Événements Personnels
&lt;/h4&gt;

&lt;p&gt;Ajoute une réunion équipe de 9h à 10h mardi au Treasure Island, puis montre-moi mon planning complet de la journée incluant mes événements personnels&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outils MCP utilisés :&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;add_personal_event(title="Réunion équipe", start_datetime="2025-12-02 09:00", end_datetime="2025-12-02 10:00", location="Treasure Island")&lt;/li&gt;
&lt;li&gt;get_schedule_by_day(day="Tuesday")&lt;/li&gt;
&lt;li&gt;get_personal_events(day="Tuesday")&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Requêtes Complexes - Combinaison avec d'Autres Sources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Planification Optimisée avec Géolocalisation
&lt;/h4&gt;

&lt;p&gt;Je loge au Treasure Island. Trouve-moi les sessions IA mardi au Venetian, calcule les temps de trajet, vérifie la météo prévue, et suggère des restaurants proches pour déjeuner entre les sessions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources de données combinées :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serveur MCP re:Invent&lt;/strong&gt; : Sessions et planning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Maps API&lt;/strong&gt; : Distances et temps de trajet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenWeather API&lt;/strong&gt; : Prévisions météorologiques&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yelp/Google Places&lt;/strong&gt; : Restaurants et avis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flm9birdrjsw0j0kx86ul.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flm9birdrjsw0j0kx86ul.webp" alt="Écosystème MCP Étendu" width="462" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Réponse coordonnée :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📋 Sessions IA trouvées au Venetian - Mardi:
• 10:30-11:30 | CNS417 - Networking and observability strategies for Kubernetes
• 13:00-14:00 | AIM304 - Building AI-powered applications with Amazon Bedrock
• 15:30-16:30 | MLO315 - Scaling machine learning operations on AWS

🚶 Temps de trajet depuis Treasure Island:
• Venetian: 18 minutes à pied ou 8 minutes en navette gratuite
• Navettes toutes les 15 minutes de 7h à 23h

🌤️ Météo prévue mardi:
• Ensoleillé, 24°C, vent léger
• Aucune précipitation prévue
• Idéal pour marcher entre les hôtels

🍽️ Restaurants recommandés près du Venetian (12h-14h):
• Bouchon Bistro - Cuisine française, 4.5⭐ (5min à pied)
• TAO Asian Bistro - Cuisine asiatique, 4.3⭐ (2min à pied)
• Yardbird - Cuisine américaine, 4.4⭐ (8min à pied)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Analyse Comparative Multi-Critères
&lt;/h4&gt;

&lt;p&gt;Compare les sessions de sécurité niveau 400 entre le Venetian et MGM mercredi, vérifie les disponibilités d'hôtels si je veux changer de lieu, et estime le budget total incluant transport et repas&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources de données combinées :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serveur MCP re:Invent&lt;/strong&gt; : Sessions de sécurité niveau 400&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Booking.com API&lt;/strong&gt; : Disponibilités et prix hôtels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uber/Lyft API&lt;/strong&gt; : Coûts de transport&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restaurant APIs&lt;/strong&gt; : Prix moyens des repas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analyse générée :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🔒 Sessions Sécurité Niveau 400 - Mercredi:

📍 VENETIAN (3 sessions):
• 10:30-11:30 | SEC407 - Building robust container security pipeline
• 14:00-15:00 | SEC412 - Advanced threat detection with AWS GuardDuty
• 16:30-17:30 | SEC419 - Zero-trust architecture implementation

📍 MGM (2 sessions):
• 11:30-12:30 | SEC408 - Cryptographic best practices for cloud
• 15:00-16:00 | SEC415 - Advanced IAM policies and cross-account access

🏨 Disponibilités Hôtels (mercredi soir):
• Venetian: 299$/nuit (Deluxe Suite disponible)
• MGM: 189$/nuit (Grand King disponible)
• Treasure Island: 149$/nuit (votre réservation actuelle)

💰 Estimation Budget Changement vers Venetian:
• Surcoût hôtel: +150$ (299$ - 149$)
• Transport économisé: -25$ (moins de trajets)
• Repas sur place: +40$ (restaurants plus chers)
• TOTAL: +165$ pour optimiser votre temps

📊 Recommandation: Rester au Treasure Island
• Économie de 165$ avec seulement 15min de trajet supplémentaire
• Sessions MGM accessibles en 12min de navette
• Plus de flexibilité pour les repas et pauses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages de l'Approche Multi-Sources
&lt;/h3&gt;

&lt;p&gt;Kiro orchestre automatiquement les différents serveurs MCP pour fournir des réponses complètes et actionnables, transformant des requêtes complexes en plans d'action.&lt;br&gt;
L'IA analyse les contraintes multiples (temps, budget, préférences, disponibilités) pour proposer les meilleures solutions sans intervention manuelle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Défis d'un Premier Projet Open Source
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Qualité et Robustesse du Code
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Défi :&lt;/strong&gt; Assurer la qualité d'un projet destiné à être public et réutilisable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approche :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tests unitaires obligatoires pour chaque composant&lt;/li&gt;
&lt;li&gt;Gestion d'erreurs affinées&lt;/li&gt;
&lt;li&gt;Documentation technique complète avec exemples d'utilisation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance et Scalabilité
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Contraintes identifiées :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temps de réponse &amp;lt; 2s avec 2200+ sessions&lt;/li&gt;
&lt;li&gt;Gestion mémoire efficace du cache&lt;/li&gt;
&lt;li&gt;Concurrence SQLite avec verrous appropriés&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solutions implémentées :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Index de base de données optimisés&lt;/li&gt;
&lt;li&gt;Cache à deux niveaux (mémoire + SQLite)&lt;/li&gt;
&lt;li&gt;Pagination intelligente des résultats&lt;/li&gt;
&lt;li&gt;Requêtes asynchrones vers les sources externes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Leçons Apprises et Perspectives
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ce qui a Bien Fonctionné
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Architecture MCP :&lt;/strong&gt; Le protocole MCP s'est révélé parfaitement adapté à ce type d'application. La découverte automatique des outils et l'invocation contextuelle par l'IA créent une expérience utilisateur impresionnante.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Écosystème reinvent-planner.cloud :&lt;/strong&gt; S'appuyer sur l'API de Raphael Manke a considérablement accéléré le développement. Cette approche illustre l'importance de réutiliser des composants de qualité plutôt que de réinventer la roue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Méthodologie Kiro :&lt;/strong&gt; Le workflow Requirements → Design → Tasks a structuré le développement et évité les écueils classiques des projets sans spécification claire et partagée. On a ainsi une référence pour l'évolution du projet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choix techniques :&lt;/strong&gt; SQLite + cache mémoire + httpx async forment une stack performante pour une application légère.&lt;/p&gt;

&lt;h3&gt;
  
  
  Évolutions Futures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Assistant IA :&lt;/strong&gt; Intégration de recommandations personnalisées basées sur l'historique utilisateur et les préférences déclarées.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Écosystème MCP étendu :&lt;/strong&gt; Développement ou intégration de serveurs MCP complémentaires (géolocalisation, hôtellerie, météo) pour créer un assistant de voyage complet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collaboration :&lt;/strong&gt; Partage de listes de favoris entre participants, recommandations sociales basées sur les profils similaires.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analytics avancées :&lt;/strong&gt; Métriques d'utilisation pour optimiser l'expérience utilisateur et identifier les tendances de participation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migration progressive vers le web :&lt;/strong&gt; Évolution de l'architecture locale vers un modèle hybride puis entièrement web pour maximiser l'accessibilité et les fonctionnalités collaboratives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Améliorations avec les Services AWS
&lt;/h2&gt;

&lt;p&gt;En tant qu'architecte AWS, l'évolution naturelle de ce projet serait d'exploiter l'écosystème AWS pour transformer le serveur MCP local en une plateforme cloud native robuste et scalable. Voici les améliorations clés que les services AWS pourraient apporter :&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Cloud Native avec AWS
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Infrastructure Serverless
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsz9eanba7r6or5ooocdr.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsz9eanba7r6or5ooocdr.webp" alt="Infrastructure Serverless" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fonctionnalités Avancées Possibles
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Notifications Intelligentes avec &lt;a href="https://docs.aws.amazon.com/sns" rel="noopener noreferrer"&gt;Amazon Simple Notification Service (SNS)&lt;/a&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conflits détectés&lt;/strong&gt; : Sessions en conflit avec événements personnels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nouvelles sessions&lt;/strong&gt; : Correspondant aux intérêts utilisateur&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimisations&lt;/strong&gt; : Suggestions de planning plus efficace&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rappels contextuels&lt;/strong&gt; : Basés sur la localisation et l'heure&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Analytics Avancées avec &lt;a href="https://docs.aws.amazon.com//quicksight" rel="noopener noreferrer"&gt;Amazon QuickSight&lt;/a&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tendances de participation&lt;/strong&gt; par service AWS, niveau, lieu&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimisation des ressources&lt;/strong&gt; : sessions peu sélectionnées, créneaux populaires&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Migration Strategy vers AWS
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Phase 1 : Lift &amp;amp; Shift
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Migration de la base SQLite vers &lt;a href="https://docs.aws.amazon.com/dynamodb" rel="noopener noreferrer"&gt;Amazon DynamoDB&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Déploiement des &lt;a href="https://docs.aws.amazon.com//lambda" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; functions pour chaque outil MCP&lt;/li&gt;
&lt;li&gt;Configuration d'&lt;a href="https://docs.aws.amazon.com/apigateway" rel="noopener noreferrer"&gt;Amazon API Gateway&lt;/a&gt; et authentification &lt;a href="https://docs.aws.amazon.com//cognito" rel="noopener noreferrer"&gt;Amazon Cognito&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phase 2 : Cloud Native
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Intégration d'&lt;a href="https://docs.aws.amazon.com//elasticache" rel="noopener noreferrer"&gt;Amazon ElastiCache&lt;/a&gt; pour le cache distribué&lt;/li&gt;
&lt;li&gt;Mise en place d'&lt;a href="https://docs.aws.amazon.com//eventbridge" rel="noopener noreferrer"&gt;Amazon EventBridge&lt;/a&gt; pour l'orchestration&lt;/li&gt;
&lt;li&gt;Déploiement du frontend avec &lt;a href="https://docs.aws.amazon.com//amplify" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; ou &lt;a href="https://docs.aws.amazon.com//s3" rel="noopener noreferrer"&gt;Amazon Simple Storage Service (S3)&lt;/a&gt; + Amazon CloudFront&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phase 3 : Intelligence Augmentée
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Intégration d'&lt;a href="https://docs.aws.amazon.com//bedrock" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; pour les recommandations&lt;/li&gt;
&lt;li&gt;Déploiement des analytics avec QuickSight&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette évolution vers AWS transformerait le serveur MCP local en une plateforme cloud native robuste, capable de servir de nombreux utilisateurs simultanément tout en maintenant des coûts optimisés grâce à l'architecture serverless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hébergement Web avec FastMCP
&lt;/h2&gt;

&lt;p&gt;Une approche plus simple et accessible consiste à transformer le serveur MCP local en service web public en utilisant des frameworks spécialisés comme FastMCP.&lt;/p&gt;

&lt;p&gt;Avantages du Déploiement Web :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aucune installation&lt;/strong&gt; requise côté client&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration simple&lt;/strong&gt; : URL + token d'authentification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibilité&lt;/strong&gt; avec tous les clients MCP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mises à jour&lt;/strong&gt; instantanées pour tous les utilisateurs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  FastMCP : Framework pour Serveurs MCP Web
&lt;/h3&gt;

&lt;p&gt;FastMCP est un framework Python moderne qui simplifie la création de serveurs MCP accessibles via HTTP/WebSocket, permettant de transformer rapidement un serveur MCP local en service web public.&lt;/p&gt;

&lt;h4&gt;
  
  
  Architecture Web Simplifiée
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1zqxqmbqud6ypa6qwpqw.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1zqxqmbqud6ypa6qwpqw.webp" alt="Architecture Web Simplifiée" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cette solution est plus simple qu'une migration vers du cloud native AWS, mais nécessite une ou plusieurs instances de calcul disponible en continue. Cette solution sera donc moins économique, et ne pourra être rentable que pour un nombre élevé d'utilisateurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ce premier projet open source m'a permis de découvrir la puissance du Model Context Protocol et de profiter de l'efficacité de Kiro pour structurer le développement. L'architecture en couches, la gestion intelligente du cache, et l'exposition de multiples outils MCP créent une solution robuste et extensible qui fonctionne bien en local.&lt;/p&gt;

&lt;p&gt;L'expérience a également souligné l'importance de l'écosystème open source : s'appuyer sur le travail de qualité de Raphael Manke avec reinvent-planner.cloud a permis de se concentrer sur la valeur ajoutée du protocole MCP plutôt que sur la collecte de données. Je le remercie une nouvelle fois de m'avoir autorisé à m'appuyer sur son travail. Le fait qu'un projet soit open source n'autorise pas à s'approprier le travail ou les données d'autrui sans permission.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leçons sur l'Architecture Locale vs Web
&lt;/h3&gt;

&lt;p&gt;L'architecture locale actuelle présente des avantages indéniables : performance optimale, confidentialité des données, fonctionnement offline et coût zéro. Cependant, l'évolution vers une architecture web hybride ouvrirait de nouvelles possibilités :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avantages immédiats d'une version web :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessibilité universelle sans installation&lt;/li&gt;
&lt;li&gt;Synchronisation multi-appareils&lt;/li&gt;
&lt;li&gt;Maintenance centralisée et mises à jour instantanées&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vision d'Avenir
&lt;/h3&gt;

&lt;p&gt;Le serveur MCP AWS re:Invent Planner démontre qu'il est possible de créer des intégrations IA sophistiquées avec des outils modernes, que ce soit en local ou dans le cloud. Plus encore, il ouvre la voie à un écosystème de serveurs MCP interconnectés : géolocalisation, hôtellerie, météo, transport. Cette vision d'assistants IA spécialisés mais coordonnés représente l'avenir des applications intelligentes.&lt;/p&gt;

&lt;p&gt;L'architecture locale actuelle constitue une base solide pour cette évolution. Les composants développés (cache intelligent, synchronisation multi-sources, gestion d'erreurs robuste) sont transposables vers une architecture web, facilitant une migration progressive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommandations pour les Architectes
&lt;/h3&gt;

&lt;p&gt;Pour les architectes souhaitant se lancer dans le développement MCP, je recommande vivement de :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commencer local&lt;/strong&gt; : Prototyper rapidement avec une architecture locale simple&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utiliser une méthodologie structurée&lt;/strong&gt; comme celle de Kiro pour maintenir la qualité&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Penser évolutivité&lt;/strong&gt; dès le départ : patterns compatibles local/web&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S'appuyer sur l'écosystème&lt;/strong&gt; existant plutôt que de tout reconstruire&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planifier la migration&lt;/strong&gt; : architecture locale comme tremplin vers le web&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioriser l'expérience utilisateur&lt;/strong&gt; : performance et simplicité avant tout&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Le code source complet du serveur &lt;a href="https://github.com/sylvainbruas/reinvent-planner" rel="noopener noreferrer"&gt;MCP AWS re:Invent Planner&lt;/a&gt; est disponible sur GitHub avec documentation technique détaillée et exemples d'utilisation. Remerciements particuliers à Raphael Manke pour &lt;a href="https://reinvent-planner.cloud/" rel="noopener noreferrer"&gt;reinvent-planner.cloud&lt;/a&gt;, source de données essentielle de ce projet.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>aws</category>
      <category>reinvent</category>
      <category>iagenerative</category>
    </item>
    <item>
      <title>Construire une App Kiro Crew pour piloter son blog technique</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Tue, 11 Aug 2026 09:22:31 +0000</pubDate>
      <link>https://dev.to/aws-builders/construire-une-app-kiro-crew-pour-piloter-son-blog-technique-39nc</link>
      <guid>https://dev.to/aws-builders/construire-une-app-kiro-crew-pour-piloter-son-blog-technique-39nc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncrxpdhtahr1t66jkz9v.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncrxpdhtahr1t66jkz9v.webp" alt="App Kiro Crew — Blog Admin Dashboard" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Dans les deux articles précédents, nous avons exploré &lt;a href="https://dev.to/blog/2026/08/kiro-crew-part1"&gt;l'architecture de Kiro Crew&lt;/a&gt; (Gateway, mémoire, sécurité) puis ses &lt;a href="https://dev.to/blog/2026/08/kiro-crew-part2"&gt;cas d'usage concrets&lt;/a&gt; (cron jobs, orchestration multi-agent, Apps existantes). Cette troisième partie est un retour d'expérience : j'ai construit une &lt;strong&gt;App Kiro Crew personnalisée&lt;/strong&gt; pour piloter l'administration de ce blog.&lt;/p&gt;

&lt;p&gt;L'objectif : regrouper dans une interface dédiée tout ce que je faisais manuellement — vérifier le statut des articles, valider les posts sociaux générés par l'agent, suivre les jobs planifiés, et monitorer les déploiements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pourquoi une App plutôt qu'un chat ?
&lt;/h2&gt;

&lt;p&gt;Certains workflows ne rentrent pas dans une fenêtre de conversation. Quand je veux :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Voir d'un coup d'œil les 3 posts sociaux en attente de validation&lt;/li&gt;
&lt;li&gt;Approuver ou rejeter un post LinkedIn d'un clic&lt;/li&gt;
&lt;li&gt;Vérifier que le dernier déploiement a passé l'audit SEO&lt;/li&gt;
&lt;li&gt;Toggler un cron job on/off sans écrire de commande&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...une UI dédiée est plus efficace qu'un échange conversationnel.&lt;/p&gt;

&lt;p&gt;C'est exactement ce que les &lt;a href="https://kiro.dev/crew/" rel="noopener noreferrer"&gt;Kiro Crew&lt;/a&gt; Apps permettent : combiner une interface React avec le runtime agent, l'event bus et les schedules dans un package cohérent.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture de l'App
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhl8b3f2y7mcgj8tvo8id.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhl8b3f2y7mcgj8tvo8id.webp" alt="Architecture de l'App Blog Admin" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Une App Kiro Crew suit une structure imposée par le framework. On peut générer un squelette via &lt;code&gt;kirocrew app init&lt;/code&gt;, mais voici la structure complète de l'app blog-admin :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kirocrew/
├── app.json               # Manifeste KiroCrew (agents, crons, UI, backend)
├── agents/                # Définitions JSON des agents
│   ├── content-validator.json
│   ├── social-writer.json
│   └── deploy-monitor.json
├── skills/                # Skills Markdown (contexte injecté aux agents)
│   ├── blog-conventions/
│   │   └── SKILL.md
│   └── social-publishing/
│       └── SKILL.md
├── backend/               # Backend Python (API interne)
│   └── server.py
├── ui/                    # Frontend React (pages du dashboard)
│   ├── src/
│   │   ├── App.tsx        # Point d'entrée (exporté en ESM)
│   │   ├── components/
│   │   ├── pages/
│   │   ├── types/
│   │   └── data/
│   ├── package.json
│   └── vite.config.ts
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stack UI&lt;/strong&gt; : &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt; 19, TypeScript 5.9, &lt;a href="https://vite.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; 6, &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; 4, &lt;a href="https://lucide.dev/" rel="noopener noreferrer"&gt;Lucide&lt;/a&gt; pour les icônes. L'UI est buildée comme un &lt;strong&gt;module ESM&lt;/strong&gt; (pas un SPA classique) car Kiro Crew injecte le composant dans son propre shell. Le routing interne utilise &lt;a href="https://reactrouter.com/" rel="noopener noreferrer"&gt;React Router&lt;/a&gt; avec un &lt;code&gt;MemoryRouter&lt;/code&gt; (Crew ne fournit pas de contexte Router parent).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt; : Python minimal (stdlib &lt;code&gt;http.server&lt;/code&gt;) qui sert une API d'articles en scannant le filesystem. Kiro Crew le démarre automatiquement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agents&lt;/strong&gt; : 3 fichiers JSON déclarant chacun un agent spécialisé avec son prompt et ses outils autorisés.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; : fichiers Markdown injectés comme contexte aux agents, encodant les conventions du blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le manifeste &lt;code&gt;app.json&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Le fichier &lt;code&gt;app.json&lt;/code&gt; est le point d'entrée de l'App auprès du runtime &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;Kiro Crew&lt;/a&gt;. Il déclare les agents, les crons, le backend et l'UI. On peut le créer manuellement ou générer un squelette avec &lt;code&gt;kirocrew app init blog-admin --ui --backend --cron&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blog-admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blog Admin Dashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dashboard d'administration pour sylvain.bruas.fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sylvainbruas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"agents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"agents/content-validator.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"agents/social-writer.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"agents/deploy-monitor.json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"skills/blog-conventions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"skills/social-publishing"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"blog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"social"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"seo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deployment"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"entryPoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backend/server.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"healthCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/health"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ui"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"entry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/index.mjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/apps/blog-admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blog Admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LayoutDashboard"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/apps/blog-admin/articles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Articles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FileText"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/apps/blog-admin/social"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Social"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Share2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/apps/blog-admin/jobs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jobs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clock"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/apps/blog-admin/deployments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Déploiements"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rocket"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"crons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"seo-audit-weekly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;604800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Audit SEO complet de tous les articles publiés"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dep-scan-daily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Scan de vulnérabilités des dépendances npm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git-hygiene"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;259200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Identifier les branches stale et commits WIP abandonnés"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redirect-check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;604800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vérifier que toutes les redirections S3 fonctionnent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"friday-summary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;604800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Résumer les déploiements de la semaine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"social-gen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"every"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Générer des posts sociaux pour le dernier article publié"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Points clés du manifeste :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;agents&lt;/code&gt;&lt;/strong&gt; : chemins relatifs vers les fichiers JSON de définition d'agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;skills&lt;/code&gt;&lt;/strong&gt; : dossiers contenant un &lt;code&gt;SKILL.md&lt;/code&gt; qui sera injecté comme contexte&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;backend&lt;/code&gt;&lt;/strong&gt; : serveur Python démarré automatiquement par Crew, avec healthcheck&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ui.entry&lt;/code&gt;&lt;/strong&gt; : le module ESM buildé par Vite — Crew l'injecte dans son shell&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ui.pages&lt;/code&gt;&lt;/strong&gt; : routes et labels affichés dans la navigation du dashboard Crew&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;crons&lt;/code&gt;&lt;/strong&gt; : jobs récurrents avec &lt;code&gt;"every"&lt;/code&gt; en secondes, un &lt;code&gt;"message"&lt;/code&gt; envoyé à l'agent, et &lt;code&gt;"enabled": false&lt;/code&gt; pour les déclarer sans les activer immédiatement&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Page Dashboard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs6wbqfk60y6px89qgu3a.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs6wbqfk60y6px89qgu3a.webp" alt="Blog Dashboard" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le Dashboard donne une vue d'ensemble en un coup d'œil :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Extrait simplifié du DashboardPage.tsx&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DashboardPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockDashboardStats&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"space-y-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatCard&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Articles publiés"&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publishedArticles&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;FileText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatCard&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Posts en attente"&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pendingSocialPosts&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Share2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"warning"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatCard&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Déploiements (semaine)"&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deploymentsThisWeek&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Rocket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatCard&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Crédits utilisés"&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;creditsUsedThisWeek&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Zap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* + Dernier déploiement avec scores audit */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* + Posts sociaux en attente */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* + Dernières exécutions de jobs */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4 métriques clés&lt;/strong&gt; : articles publiés, posts sociaux en attente de validation, déploiements de la semaine, crédits Kiro Crew consommés.&lt;/p&gt;

&lt;p&gt;En dessous : le dernier déploiement avec ses scores d'audit (SEO, Lighthouse), les posts en attente, et les dernières exécutions de jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page Validation des posts sociaux
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fga4x1ypkk8y2q0xvmr72.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fga4x1ypkk8y2q0xvmr72.webp" alt="Flux de publication sociale" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quand l'agent &lt;code&gt;social-writer&lt;/code&gt; génère des posts à partir d'un article, ils arrivent ici en statut "En attente" :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaque post&lt;/strong&gt; est affiché avec sa plateforme (X, LinkedIn, Bluesky), son contenu complet, et la date de génération&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deux boutons&lt;/strong&gt; : ✓ Approuver / ✗ Rejeter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Après approbation&lt;/strong&gt; : un bouton "Publier" apparaît pour déclencher l'envoi via l'API de la plateforme&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'idée est de garder l'humain dans la boucle pour la publication sociale — l'agent rédige, vous validez. Le mode &lt;code&gt;supervised&lt;/code&gt; dans le manifeste Crew garantit que rien ne part sans approbation explicite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page Jobs planifiés
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2sqsn6xftvn3v0j249yp.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2sqsn6xftvn3v0j249yp.webp" alt="Cycle de vie d'un cron job" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5km3lwaj9xo1t4lpyay5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5km3lwaj9xo1t4lpyay5.webp" alt="Cron Dashboard" width="799" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cette page expose les 6 jobs déclarés dans &lt;code&gt;app.json&lt;/code&gt; avec une interface de gestion :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Toggle on/off&lt;/strong&gt; pour activer/désactiver un job sans toucher au manifeste&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bouton "Run"&lt;/strong&gt; pour déclencher une exécution manuelle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Panel expandable&lt;/strong&gt; montrant : durée de la dernière exécution, crédits consommés, output terminal, historique des runs
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Chaque job affiche son schedule et son dernier output&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRun&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-900 rounded-lg p-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-green-400 whitespace-pre-line font-mono"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Point économique&lt;/strong&gt; : les jobs sont déclarés avec &lt;code&gt;"enabled": false&lt;/code&gt; dans le manifeste. Cela permet de versionner la configuration sans déclencher d'exécutions dès l'installation. On active ensuite individuellement via le toggle dans l'interface, ou en CLI avec &lt;code&gt;kirocrew cron enable blog-admin/seo-audit-weekly&lt;/code&gt;. Le scan de dépendances et la vérification des redirections sont des scripts purs (0 crédit). Seuls l'audit SEO, le résumé de fin de semaine et la génération de posts sociaux consomment des crédits d'inférence.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Fréquence&lt;/th&gt;
&lt;th&gt;Crédits/run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Audit SEO&lt;/td&gt;
&lt;td&gt;Lundi 8h&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scan dépendances&lt;/td&gt;
&lt;td&gt;Weekdays 9h&lt;/td&gt;
&lt;td&gt;0 (script)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nettoyage Git&lt;/td&gt;
&lt;td&gt;Mar/Jeu 10h&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vérification redirections&lt;/td&gt;
&lt;td&gt;Mercredi 10h&lt;/td&gt;
&lt;td&gt;0 (script)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Résumé fin de semaine&lt;/td&gt;
&lt;td&gt;Vendredi 16h&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Génération posts sociaux&lt;/td&gt;
&lt;td&gt;À la publication&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total estimé&lt;/strong&gt; : ~18 crédits/semaine, soit environ $3/mois sur un plan Pro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Déployer l'App sur Kiro Crew
&lt;/h2&gt;

&lt;p&gt;Pour enregistrer et exécuter cette App dans votre instance Kiro Crew :&lt;/p&gt;

&lt;h3&gt;
  
  
  Prérequis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;Kiro Crew&lt;/a&gt; installé et le Gateway actif (&lt;code&gt;kirocrew gateway&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Un compte Kiro authentifié (plan Free minimum, Pro recommandé)&lt;/li&gt;
&lt;li&gt;Node.js 18+ pour le build de l'UI&lt;/li&gt;
&lt;li&gt;Python 3.10+ pour le backend&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Étape 1 : Génération du squelette (optionnel)
&lt;/h3&gt;

&lt;p&gt;Si vous partez de zéro, &lt;code&gt;kirocrew app init&lt;/code&gt; génère le squelette :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kirocrew app init blog-admin &lt;span class="nt"&gt;--ui&lt;/span&gt; &lt;span class="nt"&gt;--backend&lt;/span&gt; &lt;span class="nt"&gt;--cron&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cela crée la structure de base avec &lt;code&gt;app.json&lt;/code&gt;, un agent exemple, un skill, un backend Python et un frontend Vite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Étape 2 : Build de l'UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;kirocrew/ui
pnpm &lt;span class="nb"&gt;install
&lt;/span&gt;pnpm build
&lt;span class="c"&gt;# → Génère dist/index.mjs (module ESM)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Étape 3 : Installer l'App dans Kiro Crew
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kirocrew app &lt;span class="nb"&gt;install&lt;/span&gt; /chemin/vers/kirocrew
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro Crew lit le &lt;code&gt;app.json&lt;/code&gt;, déploie les agents, programme les crons, démarre le backend, et injecte l'UI dans le dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Étape 4 : Activer et vérifier
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Activer l'app&lt;/span&gt;
kirocrew app &lt;span class="nb"&gt;enable &lt;/span&gt;blog-admin

&lt;span class="c"&gt;# Vérifier l'installation&lt;/span&gt;
kirocrew app info blog-admin

&lt;span class="c"&gt;# Lister toutes les apps installées&lt;/span&gt;
kirocrew app list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mode développement
&lt;/h3&gt;

&lt;p&gt;Pour itérer rapidement sur l'UI sans rebuild à chaque modification :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Active le live reload dans le dashboard Crew&lt;/span&gt;
kirocrew app dev blog-admin

&lt;span class="c"&gt;# Ou lancer le dev server Vite en standalone&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;kirocrew/ui &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pnpm dev
&lt;span class="c"&gt;# → http://localhost:3100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kirocrew app dev&lt;/code&gt; active le mode no-store + live reload sur les changements de fichiers. Pratique pour ajuster le dashboard sans reconstruire à chaque fois.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mode Docker (serveur always-on)
&lt;/h3&gt;

&lt;p&gt;Pour une instance persistante qui tourne même quand votre Mac est éteint :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:5476:5476 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; kirocrew-home:/home/kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/kirodotdev/kirocrew:stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Une fois le container actif, installez l'app depuis le container ou montez le répertoire en volume.&lt;/p&gt;

&lt;h3&gt;
  
  
  Désinstallation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Désactiver sans supprimer les données&lt;/span&gt;
kirocrew app disable blog-admin

&lt;span class="c"&gt;# Supprimer complètement (préserve les données par défaut)&lt;/span&gt;
kirocrew app uninstall blog-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connecter aux données réelles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Le backend Python
&lt;/h3&gt;

&lt;p&gt;Le fichier &lt;code&gt;backend/server.py&lt;/code&gt; scanne directement le filesystem pour lister les articles et calcule les statistiques :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scan_articles&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Scan le répertoire blog pour extraire les frontmatter.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;blog_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOG_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mdx_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;blog_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rglob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index.mdx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mdx_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blog_path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mdx_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;frontmatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_frontmatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;devto_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lang&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lang&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cover&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cover&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro Crew démarre ce backend automatiquement (déclaré dans &lt;code&gt;app.json&lt;/code&gt; → &lt;code&gt;backend.entryPoint&lt;/code&gt;). &lt;/p&gt;

&lt;h3&gt;
  
  
  Le hook &lt;code&gt;useApi&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Côté UI, un hook React générique gère les appels au backend via le gateway Crew :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useApi&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;FetchState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Essaie les routes du gateway, puis fallback sur le port direct&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;apiFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chaque page consomme ce hook : &lt;code&gt;useApi&amp;lt;ArticlesResponse&amp;gt;('/articles')&lt;/code&gt; pour la liste, &lt;code&gt;useApi&amp;lt;DashboardStats&amp;gt;('/stats')&lt;/code&gt; pour les compteurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ce que j'ai appris
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pièges d'intégration avec le shell Crew
&lt;/h3&gt;

&lt;p&gt;En déployant l'app pour la première fois, j'ai rencontré trois problèmes classiques d'intégration :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Le chemin &lt;code&gt;ui.entry&lt;/code&gt;&lt;/strong&gt; — Le manifeste résout le chemin depuis le dossier &lt;code&gt;ui/&lt;/code&gt; de l'app, pas depuis sa racine. Mettre &lt;code&gt;ui/dist/index.mjs&lt;/code&gt; donnait une URL doublée (&lt;code&gt;/ui/ui/dist/...&lt;/code&gt;). La valeur correcte est &lt;code&gt;dist/index.mjs&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Les externals Vite&lt;/strong&gt; — Externaliser &lt;code&gt;lucide-react&lt;/code&gt; pour réduire la taille du bundle semble logique, mais la version fournie par le runtime Crew ne contient pas forcément les mêmes exports que celle du projet. Mieux vaut bundler les icônes directement (~10 kB supplémentaires) pour éviter les erreurs &lt;code&gt;does not provide an export named 'X'&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Le thème dark du shell&lt;/strong&gt; — Le dashboard Crew est en thème sombre. Si l'app utilise des classes Tailwind en mode clair (&lt;code&gt;bg-white&lt;/code&gt;, &lt;code&gt;text-gray-900&lt;/code&gt;), il faut forcer &lt;code&gt;colorScheme: 'light'&lt;/code&gt; et un fond explicite sur le conteneur racine pour que les couleurs ne soient pas écrasées par le thème parent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Le Router&lt;/strong&gt; — Crew injecte le composant App dans son propre shell sans fournir de contexte &lt;code&gt;&amp;lt;Router&amp;gt;&lt;/code&gt;. Il faut wraper l'app avec un &lt;code&gt;&amp;lt;MemoryRouter&amp;gt;&lt;/code&gt; pour que &lt;code&gt;react-router-dom&lt;/code&gt; fonctionne.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Le modèle mental "agent + UI" fonctionne
&lt;/h3&gt;

&lt;p&gt;La séparation est nette : l'agent fait le travail lourd (rédiger, valider, scanner), l'UI donne le contrôle (approuver, rejeter, toggler, monitorer). Le mode &lt;code&gt;supervised&lt;/code&gt; est essentiel pour les actions irréversibles comme publier sur les réseaux sociaux.&lt;/p&gt;

&lt;h3&gt;
  
  
  Les scripts zero-credit sont sous-estimés
&lt;/h3&gt;

&lt;p&gt;Sur mes jobs planifiés, 2 ne consomment aucun crédit parce que ce sont des scripts bash simples. Le scan de dépendances (&lt;code&gt;npm audit --json&lt;/code&gt;) et la vérification des redirections (&lt;code&gt;scripts/test-redirects.sh&lt;/code&gt;) n'ont pas besoin de raisonnement IA. Kiro Crew les exécute directement sans appel modèle.&lt;/p&gt;

&lt;h3&gt;
  
  
  La mémoire persistante évite la dérive
&lt;/h3&gt;

&lt;p&gt;Après quelques corrections sur les posts sociaux générés ("trop long pour X", "ajoute toujours le lien canonique", "pas d'émoji dans les posts LinkedIn pro"), l'agent apprend et les prochains drafts respectent les préférences. Sans mémoire persistante, il faudrait ré-expliquer ces conventions à chaque session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Le rapport d'audit pré-deploy est un filet de sécurité
&lt;/h3&gt;

&lt;p&gt;J'ai découvert un build cassé à cause d'une image PNG (au lieu de WebP) uniquement parce que l'audit l'a détecté. Sans ce check automatique, l'article serait parti en production avec un cover manquant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Construire une App Kiro Crew se résume à :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Générer le squelette&lt;/strong&gt; avec &lt;code&gt;kirocrew app init mon-app --ui --backend --cron&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Définir&lt;/strong&gt; les agents (JSON) et skills (Markdown)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coder&lt;/strong&gt; l'UI React exportée en module ESM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Installer&lt;/strong&gt; avec &lt;code&gt;kirocrew app install ./mon-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Itérer&lt;/strong&gt; avec &lt;code&gt;kirocrew app dev mon-app&lt;/code&gt; (live reload)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La courbe d'apprentissage est faible si vous connaissez déjà React et TypeScript. Le vrai travail est dans la définition des agents et des skills.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/crew/" rel="noopener noreferrer"&gt;kiro.dev/crew&lt;/a&gt; — Page produit officielle&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;github.com/kirodotdev/KiroCrew&lt;/a&gt; — Repository GitHub&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/blog/introducing-kiro-crew/" rel="noopener noreferrer"&gt;kiro.dev/blog/introducing-kiro-crew&lt;/a&gt; — Blog post de lancement&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/aws-builders/getting-started-with-kiro-crew-23l5"&gt;dev.to/aws-builders — Getting Started with Kiro Crew&lt;/a&gt; — Guide de démarrage&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
      <category>ia</category>
      <category>devops</category>
      <category>react</category>
    </item>
    <item>
      <title>Kiro Crew : cas d'usage, Apps et perspectives — Partie 2</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:19:33 +0000</pubDate>
      <link>https://dev.to/aws-builders/kiro-crew-cas-dusage-apps-et-perspectives-partie-2-3ce6</link>
      <guid>https://dev.to/aws-builders/kiro-crew-cas-dusage-apps-et-perspectives-partie-2-3ce6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecqgl50xkl6gajxieif1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecqgl50xkl6gajxieif1.webp" alt="Kiro Crew — cas d'usage et perspectives" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Dans la &lt;a href="https://dev.to/blog/2026/08/kiro-crew-part1"&gt;première partie&lt;/a&gt;, nous avons exploré l'architecture de Kiro Crew : le Gateway, le système de mémoire, le modèle de sécurité et le positionnement dans l'écosystème Kiro. Cette seconde partie entre dans le concret : comment utiliser Kiro Crew au quotidien, quelles Apps installer, et quelles perspectives s'ouvrent pour les équipes de développement.&lt;/p&gt;
&lt;h2&gt;
  
  
  Travail planifié : cron, webhooks et heartbeats
&lt;/h2&gt;

&lt;p&gt;C'est là que Kiro Crew se distingue radicalement de tous les autres outils de coding assisté par IA. Aucun d'entre eux ne propose du travail &lt;strong&gt;planifié et non-supervisé&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3wz20py1vbc895wpit1n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3wz20py1vbc895wpit1n.webp" alt="Workflow cron et scheduling" width="799" height="333"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Jobs cron
&lt;/h3&gt;

&lt;p&gt;Les jobs cron de Kiro Crew sont timezone-aware, avec timeouts par job, jitter pour éviter les thundering herds, et skip dates pour les fenêtres de maintenance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Gérer les jobs cron&lt;/span&gt;
kirocrew cron list
kirocrew cron add
kirocrew cron remove &amp;lt;job_id&amp;gt;

&lt;span class="c"&gt;# Exemple via le chat : créer un digest matinal&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Tous les jours à 9h, résume les PRs ouvertes et flag celles qui nécessitent mon attention"&lt;/span&gt;
&lt;span class="c"&gt;# → Crée un job cron timezone-aware livré sur la surface de votre choix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Point économique crucial&lt;/strong&gt; : les jobs qui ne nécessitent pas de raisonnement IA s'exécutent comme de simples scripts ou commandes &lt;strong&gt;sans appel modèle&lt;/strong&gt;. Un health check, un &lt;code&gt;git status&lt;/code&gt;, un scan de dépendances — zéro crédit consommé. Seules les étapes qui nécessitent du raisonnement coûtent des crédits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Webhooks authentifiés
&lt;/h3&gt;

&lt;p&gt;Des endpoints authentifiés déclenchent du travail agent quand un événement externe arrive — un push CI, une alerte monitoring, un ticket créé.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Exemple d'architecture webhook&lt;/span&gt;
&lt;span class="c"&gt;# Alert PagerDuty → Webhook Kiro Crew → Investigation automatique&lt;/span&gt;

&lt;span class="c"&gt;# Le webhook reçoit un payload, démarre une session agent&lt;/span&gt;
&lt;span class="c"&gt;# qui investigue les logs et corrèle les timestamps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Heartbeats
&lt;/h3&gt;

&lt;p&gt;Les heartbeats surveillent un changement d'état : une PR qui passe en "merged", un déploiement qui échoue, un pipeline CI qui casse deux fois de suite. Quand la condition est remplie, Kiro Crew déclenche le travail associé.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F08369of1b1izh1nax4yy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F08369of1b1izh1nax4yy.webp" alt="Séquence heartbeat — monitoring et investigation automatique" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Orchestration multi-agent
&lt;/h2&gt;

&lt;p&gt;Kiro Crew peut exécuter &lt;strong&gt;plusieurs conversations en parallèle&lt;/strong&gt;, chacune avec un contexte isolé. Il délègue la recherche et l'implémentation indépendantes à des sous-agents qui retournent leurs résultats au parent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa0xqz21jqi3krfsrjb7d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa0xqz21jqi3krfsrjb7d.webp" alt="Orchestration multi-agent avec délégation" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Spawner des agents parallèles&lt;/span&gt;
kirocrew spawn run &lt;span class="s2"&gt;"Analyze the source code of module auth"&lt;/span&gt;
kirocrew spawn run &lt;span class="s2"&gt;"Write migration tests for the new schema"&lt;/span&gt;
kirocrew spawn run &lt;span class="s2"&gt;"Generate API documentation from OpenAPI spec"&lt;/span&gt;

&lt;span class="c"&gt;# Le parent coordonne, les sous-agents travaillent en isolation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Exemple concret : migration CDK
&lt;/h3&gt;

&lt;p&gt;Imaginez une migration de 12 stacks CloudFormation vers CDK. Chaque stack prend 20-40 minutes de traitement agent. Avec Kiro Crew :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F61h06j3604r4jlik2mur.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F61h06j3604r4jlik2mur.webp" alt="Flowchart migration CDK avec checkpoints" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chaque stack est un checkpoint. Si la stack 7 échoue la validation, Kiro Crew retry avec une approche différente. Vous ne repartez pas de la stack 1. Vous revenez le lendemain matin à une PR avec les 12 outputs CDK validés.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Lancer une migration avec checkpoints&lt;/span&gt;
kirocrew run migration-plan.md

&lt;span class="c"&gt;# Le fichier migration-plan.md contient les étapes,&lt;/span&gt;
&lt;span class="c"&gt;# les critères de validation, et les retry policies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Les Apps : interfaces dédiées
&lt;/h2&gt;

&lt;p&gt;Certains travaux ne rentrent pas dans une fenêtre de chat. Kiro Crew les porte dans des &lt;strong&gt;Apps&lt;/strong&gt; — des interfaces purpose-built qui combinent agents, skills, schedules, intégrations et services backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3l8d61xxbdlaw8fe3iyd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3l8d61xxbdlaw8fe3iyd.webp" alt="Écosystème des Apps Kiro Crew" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  L'App LaunchDarkly
&lt;/h3&gt;

&lt;p&gt;Un exemple concret d'intégration tierce : l'App LaunchDarkly permet de gérer les feature flags directement depuis Kiro Crew. Un agent peut trouver les références de flags dans le code, implémenter un changement derrière un flag, et vous rendre les contrôles pour le rollout.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://kiro.dev/blog/introducing-kiro-crew/" rel="noopener noreferrer"&gt;kiro.dev/blog/introducing-kiro-crew&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cas d'usage concrets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Digest matinal de PRs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# La partie "list PRs" est un script → zéro crédits&lt;/span&gt;
&lt;span class="c"&gt;# La partie "summarize" est un appel modèle → 2-3 crédits&lt;/span&gt;

&lt;span class="c"&gt;# Résultat livré sur Slack/Discord/Dashboard avant le premier café&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Coût estimé&lt;/strong&gt; : sur un plan Pro (1 000 crédits/mois à $20), un digest quotidien consomme ~60 crédits/mois. Il reste 940 crédits pour le travail interactif.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Drift de dépendances
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Job cron hebdomadaire&lt;/span&gt;
&lt;span class="c"&gt;# Semaine normale (rien à updater) → script simple → 0 crédits&lt;/span&gt;
&lt;span class="c"&gt;# Semaine avec advisory → raisonnement agent → 8-12 crédits → PR&lt;/span&gt;

kirocrew cron add &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"dependency-drift"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--schedule&lt;/span&gt; &lt;span class="s2"&gt;"0 8 * * WED"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--task&lt;/span&gt; &lt;span class="s2"&gt;"Check for outdated packages, stale branches, 
          and docs that no longer match the code. 
          If issues found, open an issue with versions, 
          breaking changes, and upgrade path."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  outils de communication
&lt;/h2&gt;

&lt;p&gt;Kiro Crew vous rejoint &lt;strong&gt;là où vous êtes déjà&lt;/strong&gt;. Pas besoin d'ouvrir un outil supplémentaire :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Outil&lt;/th&gt;
&lt;th&gt;Usage optimal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Desktop app&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Expérience locale complète, Gateway bundlé&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web dashboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Conversations parallèles, mémoire, schedules, apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DMs et threads avec streaming, approvals, notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Telegram&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DMs depuis mobile, réponses en streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discord&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DMs avec approvals en boutons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Teams&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Messages avec streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CLI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatisation directe (&lt;code&gt;kirocrew chat&lt;/code&gt;, &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;cron&lt;/code&gt;, &lt;code&gt;spawn&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;GitHub kirodotdev/KiroCrew — Surface table&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Perspectives et idées d'utilisation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldfcuggg3zvcr8ua5l9a.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldfcuggg3zvcr8ua5l9a.webp" alt="Perspectives d'utilisation" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pour une équipe DevOps/SRE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Morning standup automatique&lt;/strong&gt; : digest des alertes de la nuit, PRs en attente, état des pipelines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotation d'astreinte assistée&lt;/strong&gt; : l'agent fait la première investigation et escalade si nécessaire&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drift detection IaC&lt;/strong&gt; : comparaison quotidienne entre l'état Terraform et l'infrastructure réelle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-mortem assisté&lt;/strong&gt; : corrélation automatique des logs et timeline d'incident&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pour une web agency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit SEO récurrent&lt;/strong&gt; : scan hebdomadaire des sites clients avec rapport&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mise à jour de dépendances&lt;/strong&gt; : test + PR automatique pour les patches de sécurité&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring de performance&lt;/strong&gt; : heartbeat sur Lighthouse scores, alerte si régression&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Génération de changelog&lt;/strong&gt; : à chaque release, compilation automatique depuis les commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pour un lead technique
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code review augmentée&lt;/strong&gt; : analyse de blast radius, détection de patterns anti-DRY&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding assisté&lt;/strong&gt; : l'agent répond aux questions du nouveau avec le contexte du projet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tech radar automatisé&lt;/strong&gt; : veille hebdomadaire sur les dépendances et les nouvelles versions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation vivante&lt;/strong&gt; : mise à jour automatique des docs quand le code change&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pour un développeur solo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI personnelle&lt;/strong&gt; : tests, lint, et déploiement automatiques sur chaque push&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project memory&lt;/strong&gt; : ne jamais perdre le contexte d'un side project laissé en pause 3 mois&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pair programming asynchrone&lt;/strong&gt; : laisser Crew travailler sur un problème pendant la nuit&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limites à connaître
&lt;/h2&gt;

&lt;p&gt;Pour être complet, voici les limites actuelles :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dépendance au plan Kiro&lt;/strong&gt; : Crew est open source, mais la CLI qu'il pilote nécessite un compte Kiro et des crédits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Les agents parallèles multiplient les coûts&lt;/strong&gt; : 3 sous-agents = 3× les crédits. Architecturez vos workflows pour utiliser l'exécution séquentielle quand l'ordre compte, et le parallèle uniquement pour le travail indépendant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Crew n'architecte pas&lt;/strong&gt; : Il coordonne et exécute. Il ne prend pas les décisions de design à votre place. Vous restez l'ingénieur qui décide quoi construire et pourquoi.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ce qui change fondamentalement avec Kiro Crew, ce n'est pas la vitesse d'exécution. C'est la &lt;strong&gt;continuité&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Aujourd'hui, chaque session avec un agent IA commence par une phase de reconnexion : rappeler le contexte, re-expliquer les contraintes, relancer ce qui avait été fait la veille. Kiro Crew élimine cette friction. La mémoire persiste, les jobs tournent en arrière-plan, les webhooks réagissent pendant que vous dormez. Le matin, vous trouvez une PR prête, pas un thread de chat à relire.&lt;/p&gt;

&lt;p&gt;Mon conseil pour démarrer : identifiez un workflow qui dépasse déjà une seule session. Une migration multi-stacks, un audit de dépendances récurrent, un monitoring de drift IaC. C'est là que Crew apporte le plus de valeur — sur le travail que personne n'a le temps de faire manuellement, mais que tout le monde sait nécessaire.&lt;/p&gt;

&lt;p&gt;Le projet est sur GitHub : &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;github.com/kirodotdev/KiroCrew&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/crew/" rel="noopener noreferrer"&gt;kiro.dev/crew&lt;/a&gt; — Page produit officielle&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/blog/introducing-kiro-crew/" rel="noopener noreferrer"&gt;kiro.dev/blog/introducing-kiro-crew&lt;/a&gt; — Blog post de lancement&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;github.com/kirodotdev/KiroCrew&lt;/a&gt; — Repository GitHub (README, architecture, sécurité)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoworld.com/article/4204961/awss-kiro-crew-aims-to-turn-ai-coding-agents-into-autonomous-engineering-teams.html" rel="noopener noreferrer"&gt;infoworld.com — AWS's Kiro Crew aims to turn AI coding agents into autonomous engineering teams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/sarvar_04/introducing-kiro-crew-awss-open-source-ai-agent-orchestrator-1e63"&gt;dev.to/sarvar_04 — Introducing Kiro Crew: AWS's Open-Source AI Agent Orchestrator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://siliconangle.com/2026/08/04/aws-launches-kiro-crew-autonomous-agentic-orchestrator-24-7-code-development/" rel="noopener noreferrer"&gt;siliconangle.com — AWS launches Kiro Crew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.opensourceforu.com/2026/08/aws-open-sources-kiro-crew-for-autonomous-ai-engineering-teams/" rel="noopener noreferrer"&gt;opensourceforu.com — AWS Open Sources Kiro Crew&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
      <category>ia</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Kiro Crew : l'orchestrateur multi-agents qui travaille pendant que vous dormez — Partie 1</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:19:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/kiro-crew-lorchestrateur-multi-agents-qui-travaille-pendant-que-vous-dormez-partie-1-2a37</link>
      <guid>https://dev.to/aws-builders/kiro-crew-lorchestrateur-multi-agents-qui-travaille-pendant-que-vous-dormez-partie-1-2a37</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecqgl50xkl6gajxieif1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecqgl50xkl6gajxieif1.webp" alt="Kiro Crew — orchestrateur multi-agents persistant" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Dans un &lt;a href="https://dev.to/blog/2026/07/kiro-starter"&gt;précédent article&lt;/a&gt;, nous avons exploré la plateforme Kiro dans sa globalité : IDE, CLI, Web, et la construction d'un starter kit pour une web agency. Depuis, l'écosystème Kiro a pris une dimension supplémentaire avec le lancement de &lt;strong&gt;Kiro Crew&lt;/strong&gt; le 4 août 2026 — un workspace de développement persistant, open source sous licence Apache 2.0, qui transforme les agents IA en coéquipiers autonomes.&lt;/p&gt;

&lt;p&gt;Cette série en deux parties explore Kiro Crew en profondeur. Dans cette première partie : l'origine, l'architecture, le système de mémoire et le modèle de sécurité. La &lt;a href="https://dev.to/blog/2026/08/kiro-crew-part2"&gt;seconde partie&lt;/a&gt; couvre les cas d'usage concrets, les Apps, les exemples de code et les perspectives d'utilisation.&lt;/p&gt;
&lt;h2&gt;
  
  
  De MeshClaw à Kiro Crew : l'origine
&lt;/h2&gt;

&lt;p&gt;Kiro Crew est né d'un projet interne chez Amazon, baptisé &lt;strong&gt;MeshClaw&lt;/strong&gt;. Ils voulaient quelque chose de simple : lancer une tâche, partir, revenir à quelque chose de reviewable, et exécuter plusieurs tâches en parallèle au lieu de surveiller un seul prompt à la fois.&lt;/p&gt;
&lt;h2&gt;
  
  
  Le problème fondamental
&lt;/h2&gt;

&lt;p&gt;Le blog officiel de lancement (&lt;a href="https://kiro.dev/blog/introducing-kiro-crew/" rel="noopener noreferrer"&gt;kiro.dev/blog/introducing-kiro-crew&lt;/a&gt;) pose le problème clairement : &lt;strong&gt;le développeur est devenu la couche d'intégration entre ses propres outils&lt;/strong&gt;. Le travail d'ingénierie réel n'est jamais une tâche dans une session. Il traverse des repos, des outils, des reviews, et des jours.&lt;/p&gt;

&lt;p&gt;Quand vous fermez un onglet de Kiro CLI ou IDE, le contexte disparaît. La prochaine session commence à froid. Vous passez les 10 premières minutes à ré-expliquer où vous en étiez. Et le moment où vous partez, tout s'arrête.&lt;/p&gt;

&lt;p&gt;Kiro Crew rompt ce pattern en rendant le workspace &lt;strong&gt;persistant&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La mémoire se maintient entre les sessions&lt;/li&gt;
&lt;li&gt;Les corrections deviennent des leçons durables&lt;/li&gt;
&lt;li&gt;Les patterns répétés deviennent des skills réutilisables&lt;/li&gt;
&lt;li&gt;Le travail continue sur un schedule même quand vous n'êtes plus là&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Architecture : la Gateway au centre
&lt;/h2&gt;

&lt;p&gt;L'architecture de Kiro Crew repose sur une séparation claire entre &lt;strong&gt;là où l'agent tourne&lt;/strong&gt; et &lt;strong&gt;là où vous travaillez avec lui&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7nui8eokl17l5asja4d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7nui8eokl17l5asja4d.webp" alt="Architecture Kiro Crew — Gateway et sessions" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;README du repository GitHub kirodotdev/KiroCrew&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Les trois couches
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Couche&lt;/th&gt;
&lt;th&gt;Rôle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Surfaces&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Desktop app, web dashboard, Slack, Telegram, Discord, Teams, Webex, WeCom, CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Process long-running qui route les messages, persiste l'état des sessions, injecte mémoire et skills, lance le travail schedulé, coordonne les sous-agents, broker les approbations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent sessions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sessions isolées pilotées par &lt;code&gt;kiro-cli&lt;/code&gt; via ACP, avec accès aux outils MCP et aux modèles&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Le Gateway est le cœur du système. C'est un processus unique qui tourne sur votre machine (Mac, Linux, conteneur Docker, ou serveur distant). Les conversations, la mémoire et les index restent sur cet hôte. Les requêtes aux modèles passent par &lt;code&gt;kiro-cli&lt;/code&gt; selon votre configuration de compte.&lt;/p&gt;
&lt;h3&gt;
  
  
  Déploiement
&lt;/h3&gt;

&lt;p&gt;Kiro Crew supporte plusieurs modes de déploiement, tous basés sur le même principe : Gateway + sessions agent + état sur un seul hôte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Installation one-liner (stable)&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.crew.kiro.dev/cli.sh | sh

&lt;span class="c"&gt;# Ou Docker pour un serveur always-on&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:5476:5476 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; kirocrew-home:/home/kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/kirodotdev/kirocrew:stable

&lt;span class="c"&gt;# Ou build from source&lt;/span&gt;
git clone https://github.com/kirodotdev/KiroCrew.git
&lt;span class="nb"&gt;cd &lt;/span&gt;KiroCrew
make build
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
kirocrew setup
kirocrew doctor
kirocrew gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;GitHub kirodotdev/KiroCrew — Quick start&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Le dashboard web est accessible sur &lt;code&gt;http://localhost:5476&lt;/code&gt; et ne nécessite aucun credential de messaging. Il bindé sur loopback par défaut — les dashboards distants requièrent une authentification par token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Client Protocol (ACP)
&lt;/h3&gt;

&lt;p&gt;Kiro Crew orchestre ses agents via l'&lt;strong&gt;Agent Client Protocol (ACP)&lt;/strong&gt;, un standard ouvert qui permet aux agents IA de fonctionner avec n'importe quel éditeur compatible. Chaque étape est observable en live : vous pouvez suivre comment l'agent planifie une tâche, spawne des sous-agents parallèles, décide quels outils appeler, gate chaque action pour approbation, et synthétise les résultats.&lt;/p&gt;

&lt;h2&gt;
  
  
  Le système de mémoire : self-learning et self-evolving
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn2if3t13x6km0qoxgr2f.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn2if3t13x6km0qoxgr2f.webp" alt="Système de mémoire Kiro Crew" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le système de mémoire de Kiro Crew ne se limite pas à "se souvenir de la dernière conversation". C'est un système à plusieurs niveaux, persistant et inspectable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trois types de mémoire
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Portée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Préférences, projets actifs, historique pertinent&lt;/td&gt;
&lt;td&gt;Cross-session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lessons&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Corrections transformées en règles durables&lt;/td&gt;
&lt;td&gt;Workspace-scoped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Patterns répétés synthétisés en fichiers Markdown nommés&lt;/td&gt;
&lt;td&gt;Éditables et partageables&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Knowledge Graph
&lt;/h3&gt;

&lt;p&gt;Les décisions architecturales, préférences de code et contexte projet atterrissent dans un &lt;strong&gt;knowledge graph&lt;/strong&gt; soutenu par des embeddings vectoriels et une recherche full-text. L'agent retrouve ce qui est pertinent au lieu de tout relire.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leçons workspace-scoped
&lt;/h3&gt;

&lt;p&gt;Un point essentiel : les leçons sont &lt;strong&gt;scopées au workspace&lt;/strong&gt;. Dites une fois à Kiro Crew « ne jamais utiliser &lt;code&gt;var&lt;/code&gt; en JavaScript » et cette correction devient une règle permanente &lt;em&gt;pour ce projet&lt;/em&gt;. Les règles du projet A ne contaminent pas le projet B.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Exemple de commande naturelle qui crée une leçon&lt;/span&gt;
&lt;span class="c"&gt;# Dans un chat Kiro Crew :&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Non, toujours exécuter les checks frontend avant de déclarer un changement terminé"&lt;/span&gt;
&lt;span class="c"&gt;# → Devient une leçon workspace-scoped appliquée dans les sessions futures&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sécurité : defense in depth
&lt;/h2&gt;

&lt;p&gt;Donner à un agent un accès réel à votre code et votre CI exige un modèle de sécurité sérieux. Kiro Crew est construit avec la sécurité dès le premier commit, sur 7 couches distinctes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1vmb2jbyw5m8kmmavao.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1vmb2jbyw5m8kmmavao.webp" alt="Les 7 couches de sécurité de Kiro Crew" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Détail des couches
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Couche&lt;/th&gt;
&lt;th&gt;Fonction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS Sandbox&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Isolation namespace (Linux) ou Seatbelt (macOS). Modes : standard, strict, off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tool Approval Gates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chaque requête outil peut être reviewée dans le dashboard, Slack ou Telegram&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sensitive Path Blocking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blocage d'accès aux chemins protégés (credentials, clés SSH, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Write-Protected Paths&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Certains fichiers/dossiers sont en lecture seule pour l'agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Denied Command Patterns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;137 patterns deny bloquent les commandes destructives et l'exfiltration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP Input Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Validation des entrées et redaction des sorties avant qu'elles n'atteignent le chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audit &amp;amp; Signed Events&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Log structuré de chaque action, vérifiable avec &lt;code&gt;kirocrew security verify&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Audit et gouvernance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inspecter les événements de sécurité&lt;/span&gt;
kirocrew security events

&lt;span class="c"&gt;# Auditer les actions passées&lt;/span&gt;
kirocrew security audit

&lt;span class="c"&gt;# Vérifier l'intégrité des logs&lt;/span&gt;
kirocrew security verify

&lt;span class="c"&gt;# Afficher la politique de gouvernance active&lt;/span&gt;
kirocrew policy show
kirocrew policy validate
kirocrew policy explain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La gouvernance suit un modèle &lt;strong&gt;tightest-wins&lt;/strong&gt; : une app ou un agent peut restreindre les permissions mais ne peut jamais élargir le plafond défini par l'entreprise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Politique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;de&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;gouvernance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;enterprise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(exemple)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"boot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"fail_closed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"capabilities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"telemetry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Source : &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;GitHub kirodotdev/KiroCrew — Security and control&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pourquoi l'open source change tout
&lt;/h3&gt;

&lt;p&gt;L'argument clé : un workspace avec accès à votre code, CI et credentials ne devrait &lt;strong&gt;jamais&lt;/strong&gt; être une boîte noire. Parce que Kiro Crew est open source, vous pouvez :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lire le code source et tracer l'exécution&lt;/li&gt;
&lt;li&gt;Vérifier que le sandbox sandboxe réellement&lt;/li&gt;
&lt;li&gt;Auditer les patterns deny et les chemins protégés&lt;/li&gt;
&lt;li&gt;Confirmer qu'aucune donnée ne quitte votre machine sans votre consentement&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kiro Crew dans l'écosystème Kiro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tvtivfp72rtlgefe5we.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tvtivfp72rtlgefe5we.webp" alt="Les surfaces de l'écosystème Kiro" width="799" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kiro dispose maintenant de &lt;strong&gt;quatre surfaces&lt;/strong&gt; : IDE, CLI, Web et Crew. Voici comment elles se positionnent :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Kiro IDE&lt;/th&gt;
&lt;th&gt;Kiro CLI&lt;/th&gt;
&lt;th&gt;Kiro Web&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kiro Crew&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sessions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Interactives&lt;/td&gt;
&lt;td&gt;Interactives&lt;/td&gt;
&lt;td&gt;Interactives&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Persistantes, autonomes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scheduling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cron, webhooks, heartbeats&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Sous-agents&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Orchestration parallèle complète&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mémoire&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Session only&lt;/td&gt;
&lt;td&gt;Session only&lt;/td&gt;
&lt;td&gt;Session only&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cross-session persistante&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Travail sans surveillance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Oui&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Oui&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Compatibilité avec la configuration existante
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Point crucial&lt;/strong&gt; : Kiro Crew lit votre configuration &lt;code&gt;.kiro&lt;/code&gt; existante. Vos steering files, skills et custom agents sont automatiquement disponibles sans migration ni reconfiguration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Votre structure .kiro existante fonctionne directement&lt;/span&gt;
.kiro/
├── steering/          &lt;span class="c"&gt;# → Injecté dans les sessions Crew&lt;/span&gt;
├── skills/            &lt;span class="c"&gt;# → Disponible comme skills Crew&lt;/span&gt;
├── agents/            &lt;span class="c"&gt;# → Utilisable dans les sessions&lt;/span&gt;
└── settings/
    └── mcp.json       &lt;span class="c"&gt;# → MCP servers disponibles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Commandes essentielles
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Démarrer une session de chat&lt;/span&gt;
kirocrew chat

&lt;span class="c"&gt;# Exécuter une tâche&lt;/span&gt;
kirocrew run

&lt;span class="c"&gt;# Gérer les jobs cron&lt;/span&gt;
kirocrew cron

&lt;span class="c"&gt;# Spawner des agents parallèles&lt;/span&gt;
kirocrew spawn

&lt;span class="c"&gt;# Installer comme service système&lt;/span&gt;
kirocrew service &lt;span class="nb"&gt;install
&lt;/span&gt;kirocrew service status

&lt;span class="c"&gt;# Suivre les logs&lt;/span&gt;
kirocrew logs &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion de la partie 1
&lt;/h2&gt;

&lt;p&gt;Kiro Crew représente un saut qualitatif dans l'outillage développeur : on passe d'agents conversationnels éphémères à un &lt;strong&gt;workspace persistant, auto-apprenant et autonome&lt;/strong&gt;. L'architecture Gateway/Sessions/ACP est solide, le modèle de sécurité est conçu pour la production, et l'open source garantit la transparence.&lt;/p&gt;

&lt;p&gt;Dans la &lt;a href="https://dev.to/blog/2026/08/kiro-crew-part2"&gt;seconde partie&lt;/a&gt;, nous verrons les cas d'usage concrets : jobs cron, investigation d'incidents multi-repo, migration avec checkpoints, Apps (DevFleets, Issue Radar, Code Review Sage), et les perspectives d'utilisation pour une équipe de développement.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/crew/" rel="noopener noreferrer"&gt;kiro.dev/crew&lt;/a&gt; — Page produit officielle&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/blog/introducing-kiro-crew/" rel="noopener noreferrer"&gt;kiro.dev/blog/introducing-kiro-crew&lt;/a&gt; — Blog post de lancement&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;github.com/kirodotdev/KiroCrew&lt;/a&gt; — Repository GitHub&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
      <category>ia</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Accès centralisé aux comptes racine pour votre organisation AWS</title>
      <dc:creator>sylvainbruas</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:16:12 +0000</pubDate>
      <link>https://dev.to/aws-builders/acces-centralise-aux-comptes-racine-pour-votre-organisation-aws-59ak</link>
      <guid>https://dev.to/aws-builders/acces-centralise-aux-comptes-racine-pour-votre-organisation-aws-59ak</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6hhgjq2x3539ry0wl4m.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6hhgjq2x3539ry0wl4m.webp" alt="Accès centralisé aux comptes racine pour votre organisation AWS" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Chaque responsable de &lt;a href="https://docs.aws.amazon.com/fr_fr/prescriptive-guidance/latest/migration-aws-environment/understanding-landing-zones.html" rel="noopener noreferrer"&gt;landing zone AWS&lt;/a&gt; cherche à réduire la surface d'attaque pour protéger au mieux les systèmes d'information. Une des ressources critiques de la landing zone est le compte racine associé à chaque compte AWS.&lt;/p&gt;

&lt;p&gt;Les comptes AWS, même intégrés dans une &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_introduction.html" rel="noopener noreferrer"&gt;organisation&lt;/a&gt;, possèdent chacun un &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html" rel="noopener noreferrer"&gt;compte racine&lt;/a&gt;. Ces comptes racine étaient indispensables pour effectuer certaines &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks" rel="noopener noreferrer"&gt;opérations critiques&lt;/a&gt;, comme par exemple lors de la configuration initiale du compte et pour débloquer des buckets &lt;a href="https://docs.aws.amazon.com/fr_fr/AmazonS3/latest/userguide/Welcome.html" rel="noopener noreferrer"&gt;Amazon Simple Storage Service (Amazon S3)&lt;/a&gt;, des queues &lt;a href="https://docs.aws.amazon.com/fr_fr/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html" rel="noopener noreferrer"&gt;Amazon Simple Queue Service (AmazonSQS)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ces opérations, qui doivent rester le plus rare possible, nécessitaient l'utilisation du compte racine et la récupération du dispositif &lt;a href="https://docs.aws.amazon.com/fr_fr/IAM/latest/UserGuide/id_credentials_mfa.html" rel="noopener noreferrer"&gt;MFA&lt;/a&gt; physique dans le coffre de l'entreprise. Ces démarches fastidieuses pour se connecter au compte racine étaient nécessaires pour assurer la sécurité. Elles n'étaient pas suffisante pour totalement protéger le compte AWS, car un collaborateur utilisant le compte racine peut effectuer n'importe quel appel API de services AWS, ce qui représente un risque élevé.&lt;/p&gt;

&lt;p&gt;Depuis mi-novembre 2024, AWS propose une nouvelle méthode pour simplifier ces &lt;a href="https://aws.amazon.com/fr/about-aws/whats-new/2024/11/manage-root-access-aws-identity-access-management/" rel="noopener noreferrer"&gt;opérations&lt;/a&gt; via l'accès racine centralisé.&lt;br&gt;
Il n'est plus nécessaire de récupérer le mot de passe du compte racine de chaque compte membre de l'organisation. Les opérations de &lt;a href="https://repost.aws/knowledge-center/s3-accidentally-denied-access" rel="noopener noreferrer"&gt;déblocage de bucket S3&lt;/a&gt; ou de &lt;a href="https://repost.aws/knowledge-center/sqs-queue-access-issues-deny-policy" rel="noopener noreferrer"&gt;file d'attente SQS&lt;/a&gt; peuvent être initiées par un utilisateur IAM ayant les autorisations nécessaires sur un compte membre. La gestion de la récupération du mot de passe racine est maintenant centralisée au niveau du compte payeur.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw96z0xcavjo00trwtfdw.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw96z0xcavjo00trwtfdw.webp" alt="Avant après la centralisation des comptes racine" width="722" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En utilisant cette méthode, nous pouvons réduire la surface d'attaque et simplifier le modèle opérationnel pour résoudre les erreurs liées à IAM, SQS et S3. Cette méthode permet également de réduire la charge de travail lors du départ d'un administrateur des comptes AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foavuo908g5lqosein0tz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foavuo908g5lqosein0tz.webp" alt="Départ dun administrateur" width="722" height="457"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Notre environnement pour cet article
&lt;/h2&gt;

&lt;p&gt;Nous disposons d'une organisation existante avec plusieurs comptes membres pour lesquels nous avons configuré un mot de passe pour chaque compte racine ainsi que l'authentification multi-facteurs (MFA). Un nouveau compte Sandbox nommé &lt;strong&gt;Sandbox Sylvain&lt;/strong&gt; a été créé, mais nous ne nous y sommes jamais connectés.&lt;/p&gt;

&lt;p&gt;Nous avons également un compte &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/break-glass-access.html" rel="noopener noreferrer"&gt;Breaking Glass&lt;/a&gt; avec quelques utilisateurs IAM de secours nous permettant de nous connecter si AWS Identity Center ne fonctionne plus comme attendu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmb1mnn88gjqam1n3ur9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmb1mnn88gjqam1n3ur9.webp" alt="Organization pour le test" width="712" height="272"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Mise en place
&lt;/h2&gt;

&lt;p&gt;La première étape est d'activer l'accès centralisé aux comptes racine au niveau du compte payeur de votre organisation. Cette fonctionnalité se trouve au niveau d'IAM si vous passez via la console, vous pouvez également faire cette opération via la CLI.&lt;/p&gt;

&lt;p&gt;Pour effectuer cette première étape, vous devez avoir &lt;a href="https://docs.aws.amazon.com/fr_fr/IAM/latest/UserGuide/id_root-enable-root-access.html" rel="noopener noreferrer"&gt;les autorisations suivantes&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  iam:EnableOrganizationsRootCredentialsManagement
  iam:EnableOrganizationsRootSessions
  organizations:RegisterDelegatedAdministrator
  organizations:EnableAwsServiceAccess
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Via la CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; aws iam enable-organizations-root-credentials-management
 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; aws iam enable-organizations-root-sessions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Via la console
&lt;/h3&gt;

&lt;p&gt;Nous allons dans le service IAM puis cliquer sur le menu de gauche sur le lien &lt;strong&gt;Root Access Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4z1qp3vzokwc11qcq6bc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4z1qp3vzokwc11qcq6bc.webp" alt="Root Access Management" width="800" height="431"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Nous allons utiliser notre compte Breaking Glass comme compte administrateur délégué. Ainsi, nous pourrons non seulement intervenir sur les comptes membres en cas de problème avec nos comptes IAM Breaking Glass, mais en dernier recours, nous pourrons également recréer des identifiants pour le compte racine des comptes membres.&lt;/p&gt;

&lt;p&gt;Pour maintenir une observabilité maximale sur ce compte Breaking Glass, nous ajouterons de nouvelles alarmes liées aux nouvelles possibilités offertes à nos utilisateurs IAM.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vheminqvh49uascdxdh.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vheminqvh49uascdxdh.webp" alt="Root Access Management 2e écran" width="800" height="575"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Nous voyons maintenant la section &lt;strong&gt;Centralized root access for member accounts&lt;/strong&gt; activée.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cdi6x216jkshna2egty.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cdi6x216jkshna2egty.webp" alt="Root Access Management résultat" width="731" height="486"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;En cliquant de nouveau sur &lt;strong&gt;Root Access Management&lt;/strong&gt;, vous obtenez la liste des comptes, avec l'indication de la présence ou non d'accès racine. Dans notre cas, le compte Breaking Glass bénéficie de cette fonctionnalité, tandis que les autres comptes ont toujours les accès racine activés.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv6u73pq4jt2pvtugomv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwv6u73pq4jt2pvtugomv.webp" alt="Root Access Management liste des comptes" width="800" height="654"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Validation de la mise en place
&lt;/h2&gt;

&lt;p&gt;Nous n'avons pas encore récupéré le mot de passe pour le compte racine sur le compte &lt;strong&gt;Sandbox Sylvain&lt;/strong&gt;.&lt;br&gt;
Nous allons maintenant vérifier que tout cela fonctionne comme attendu, c'est à dire avoir un message d'erreur lors du processus de récupération du mot de passe.&lt;/p&gt;

&lt;p&gt;Essayons de faire un &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reset-root-password.html" rel="noopener noreferrer"&gt;reset du mot de passe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rien ne change pour la demande d'oubli du mot de passe et l'envoi de l'email se fait sans problème.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fyv36ssq7se8ky08zsr.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fyv36ssq7se8ky08zsr.webp" alt="Validation étape 1" width="368" height="278"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkft84qx80yboirdnmjgb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkft84qx80yboirdnmjgb.webp" alt="Validation étape 2" width="403" height="305"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp2z3fnr6oovajxiojxi.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp2z3fnr6oovajxiojxi.webp" alt="Validation étape 3" width="800" height="203"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Quand nous utilisons le lien, nous avons un message nous indiquant la désactivation de la fonctionnalité, comme attendu.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrsuoy2qnd0onv82mw7s.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrsuoy2qnd0onv82mw7s.webp" alt="Validation étape 4" width="533" height="289"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Il ne reste plus qu'à retirer les accès au compte racine sur tous les comptes membre de l'organisation. Vous pouvez le faire via la console ou la CLI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Utilisation de assumeRoot et moindre privilège
&lt;/h2&gt;

&lt;p&gt;Même si l'utilisation de l'API assumeRoot est limitée aux politiques IAM suivantes, il est nécessaire de restreindre son utilisation car avec IAMCreateRootUserPassword, nous pourrions réaliser une élévation de privilèges.&lt;/p&gt;

&lt;p&gt;Liste des &lt;a href="https://docs.aws.amazon.com/fr_fr/IAM/latest/UserGuide/id_root-enable-root-access.html" rel="noopener noreferrer"&gt;politiques disponibles&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; IAMAuditRootUserCredentials
 IAMCreateRootUserPassword
 IAMDeleteRootUserCredentials
 S3UnlockBucketPolicy
 SQSUnlockQueuePolicy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nous allons donc répartir les droits entre deux profils d'utilisateurs :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Administrateurs de comptes AWS&lt;/th&gt;
&lt;th&gt;Opérateurs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IAMAuditRootUserCredentials&lt;/td&gt;
&lt;td&gt;S3UnlockBucketPolicy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAMCreateRootUserPassword&lt;/td&gt;
&lt;td&gt;SQSUnlockQueuePolicy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAMDeleteRootUserCredentials&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Seuls les administrateurs d'Identity Center et de comptes AWS sont habilités à accorder les droits de connexion sur le compte racine. Ce sont eux également qui gèrent les comptes "breaking glass" et qui appliqueront les mêmes politiques sur ces comptes IAM de secours.&lt;/p&gt;

&lt;p&gt;Nous allons créer un permset dédié aux opérateurs, que nous allons appeler UnlockS3SQS. Nous avons délégué la gestion de IAM identity center au compte breaking glass, nous allons donc utiliser celui-ci pour la connexion des Administrateurs et des Opérateurs.&lt;/p&gt;

&lt;p&gt;Exemple de politique suivant le principe du moindre privilège pour permettre la gestion des comptes racines par les opérateurs via la console AWS et la CLI :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="s2"&gt;"Version"&lt;/span&gt;: &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;,
     &lt;span class="s2"&gt;"Statement"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
       &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="s2"&gt;"Sid"&lt;/span&gt;: &lt;span class="s2"&gt;"Statement1"&lt;/span&gt;,
         &lt;span class="s2"&gt;"Effect"&lt;/span&gt;: &lt;span class="s2"&gt;"Allow"&lt;/span&gt;,
         &lt;span class="s2"&gt;"Action"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
           &lt;span class="s2"&gt;"organizations:DescribeOrganization"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListAccounts"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListChildren"&lt;/span&gt;,
           &lt;span class="s2"&gt;"sts:AssumeRoot"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListAWSServiceAccessForOrganization"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListDelegatedAdministrators"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListOrganizationalUnitsForParent"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListParents"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListRoots"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:ListAccountsForParent"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:DescribeAccount"&lt;/span&gt;,
           &lt;span class="s2"&gt;"organizations:DescribeOrganizationalUnit"&lt;/span&gt;,
           &lt;span class="s2"&gt;"iam:ListOrganizationsFeatures"&lt;/span&gt;
         &lt;span class="o"&gt;]&lt;/span&gt;,
         &lt;span class="s2"&gt;"Resource"&lt;/span&gt;: &lt;span class="s2"&gt;"*"&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nous allons interdire la réactivation du compte racine des comptes membres via une &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html" rel="noopener noreferrer"&gt;Service control Policy&lt;/a&gt; (SCP). Si un adminitrateur de compte AWS doit rétablir un compte racine, il devra donc desactiver la SCP sur le compte cible avant tout autre opération.&lt;/p&gt;

&lt;p&gt;SCP pour bloquer la réactivation d'un compte racine :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="s2"&gt;"Version"&lt;/span&gt;: &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;,
       &lt;span class="s2"&gt;"Statement"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
           &lt;span class="o"&gt;{&lt;/span&gt;
               &lt;span class="s2"&gt;"Sid"&lt;/span&gt;: &lt;span class="s2"&gt;"Statement2"&lt;/span&gt;,
               &lt;span class="s2"&gt;"Effect"&lt;/span&gt;: &lt;span class="s2"&gt;"Deny"&lt;/span&gt;,
               &lt;span class="s2"&gt;"Action"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                   &lt;span class="s2"&gt;"iam:CreateLoginProfile"&lt;/span&gt;
               &lt;span class="o"&gt;]&lt;/span&gt;,
               &lt;span class="s2"&gt;"Resource"&lt;/span&gt;: &lt;span class="s2"&gt;"*"&lt;/span&gt;,
               &lt;span class="s2"&gt;"Condition"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                   &lt;span class="s2"&gt;"ForAnyValue:Bool"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                       &lt;span class="s2"&gt;"aws:AssumedRoot"&lt;/span&gt;: &lt;span class="s2"&gt;"true"&lt;/span&gt;
                   &lt;span class="o"&gt;}&lt;/span&gt;
               &lt;span class="o"&gt;}&lt;/span&gt;
           &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Réflexions sur la gouvernance
&lt;/h2&gt;

&lt;p&gt;Nous réduisons notre surface d'attaque grâce à la centralisation des accès aux comptes racine. Bien que les tentatives de force brute soient déjà compliquées avec les mécanismes de protection sur le formulaire de récupération de mot de passe, rien n'est plus efficace que la désactivation d'une fonctionnalité.&lt;/p&gt;

&lt;p&gt;Le cycle de vie et la protection des mots de passe des comptes racines sont ainsi réduits à un seul élément à gérer. En cas de départ d'un gestionnaire de la landing zone, il suffit de modifier un seul mot de passe pour s'assurer que seules les personnes habilitées auront accès aux comptes racines.&lt;br&gt;
Cette première ligne de défense est donc maintenant plus facile à gérer, elle restera renforcée par le MFA physique stocké dans un coffre, dont les gestionnaires de la landing zone n'ont pas le code.&lt;/p&gt;

&lt;p&gt;Il n'y a plus d'opérations courantes nécessitant l'utilisation du compte racine et la récupération du MFA associé. Un compte IAM supervisé est suffisant, et cette fonctionnalité ne permet qu'une liste FINIE d'actions strictement nécessaires.&lt;/p&gt;

&lt;p&gt;Nous pouvons suivre l'utilisation aisément via AWS CloudTrail, tout en maintenant le même niveau d'observabilité.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;L'utilisation de cette méthode améliore la sécurité de votre landing zone. Vous pourriez constater une baisse transitoire de votre score sur certains frameworks de sécurité. Cette fonctionnalité étant assez récente, elle n'est pas encore prise en compte et pourrait être considérée comme un compte racine sans MFA pour le protéger.&lt;br&gt;
Par exemple, &lt;a href="https://github.com/nccgroup/ScoutSuite" rel="noopener noreferrer"&gt;Scoutsuite&lt;/a&gt; considère qu'il n'y a pas de MFA associé au compte racine. Au moment de la rédaction de cet article, aucune pull request n'est ouverte pour corriger ce point.&lt;/p&gt;

&lt;p&gt;Comme nous l'avons vu tout au long de cet article, l'accès au compte racine centralisé apporte une grande facilité de gestion, mais il faut rester prudent. L'API IAMCreateRootUserPassword pourrait permettre une élévation de privilèges. Une étude des impacts sur la sécurité est donc indispensable, et le respect de la séparation des responsabilités ainsi que du principe du moindre privilège est nécessaire pour réduire les risques.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>securite</category>
      <category>gouvernance</category>
    </item>
  </channel>
</rss>
