two/main/versions/0.2.0.html
2026-10-05 19:15:15 +00:00

561 lines
No EOL
27 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr" data-content_root="../" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Bael &#8212; Documentation two 0.1.0</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "";
</script>
<!--
this give us a css class that will be invisible only if js is disabled
-->
<noscript>
<style>
.pst-js-only { display: none !important; }
</style>
</noscript>
<!-- Loaded before other Sphinx assets -->
<link href="../_static/styles/theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link href="../_static/styles/pydata-sphinx-theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=8f2a1f02" />
<link rel="stylesheet" type="text/css" href="../_static/styles/sphinx-book-theme.css?v=3c74b3bc" />
<!-- So that users can add custom icons -->
<script src="../_static/scripts/fontawesome.js?digest=8878045cc6db502f8baf"></script>
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf" />
<link rel="preload" as="script" href="../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf" />
<script src="../_static/documentation_options.js?v=57395fb6"></script>
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
<script src="../_static/scripts/sphinx-book-theme.js?v=fab101a9"></script>
<script src="../_static/translations.js?v=e6b791cb"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'versions/0.2.0';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.16.1';
DOCUMENTATION_OPTIONS.theme_switcher_json_url = '../switcher.json';
DOCUMENTATION_OPTIONS.theme_switcher_version_match = 'main';
DOCUMENTATION_OPTIONS.show_version_warning_banner =
false;
</script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Recherche" href="../search.html" />
<link rel="next" title="Michael" href="0.1.0.html" />
<link rel="prev" title="Versions" href="index.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="fr"/>
<meta name="docsearch:version" content="0.1" />
</head>
<body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode="">
<div id="pst-skip-link" class="skip-link d-print-none"><a href="#main-content">Passer au contenu principal</a></div>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>Haut de page</button>
<dialog id="pst-search-dialog">
<form class="bd-search d-flex align-items-center"
action="../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
placeholder="Search..."
aria-label="Search..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form>
</dialog>
<div class="pst-async-banner-revealer d-none">
<aside id="bd-header-version-warning" class="d-none d-print-none" aria-label="Alerte de version"></aside>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar d-print-none">
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<dialog id="pst-primary-sidebar-modal"></dialog>
<div id="pst-primary-sidebar" class="bd-sidebar-primary bd-sidebar">
<div class="sidebar-header-items sidebar-primary__section">
</div>
<div class="sidebar-primary-items__start sidebar-primary__section">
<div class="sidebar-primary-item">
<a class="navbar-brand logo" href="../index.html">
<p class="title logo__title">Documentation two 0.1.0</p>
</a></div>
<div class="sidebar-primary-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://git.g3e.fr/syonad/two" title="Dépôt" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-solid fa-code-branch fa-lg" aria-hidden="true"></i>
<span class="sr-only">Dépôt</span></a>
</li>
</ul></div>
<div class="sidebar-primary-item">
<div class="version-switcher__container dropdown pst-js-only">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div></div>
<div class="sidebar-primary-item">
<button class="btn search-button-field search-button__button pst-js-only" title="Recherche" aria-label="Recherche" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Recherche</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button></div>
<div class="sidebar-primary-item"><nav class="bd-links bd-docs-nav" aria-label="Main">
<div class="bd-toc-item navbar-nav active">
<ul class="nav bd-sidenav bd-sidenav__home-link">
<li class="toctree-l1">
<a class="reference internal" href="../index.html">
two
</a>
</li>
</ul>
<p aria-level="2" class="caption" role="heading"><span class="caption-text">Mise en œuvre</span></p>
<ul class="nav bd-sidenav">
<li class="toctree-l1 has-children"><a class="reference internal" href="../demarrage/index.html">Démarrage</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../demarrage/installation.html">Installation d’un hyperviseur</a></li>
<li class="toctree-l2"><a class="reference internal" href="../demarrage/premier-vpc.html">Premier VPC, premier subnet, première VM</a></li>
</ul>
</details></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../deploiement/index.html">Déploiement d’un cluster</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../deploiement/architecture-cluster.html">Architecture du cluster</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deploiement/image-qcow2.html">Construction de l’image qcow2</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deploiement/routeurs.html">Routeurs</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deploiement/premier-hyperviseur.html">Premier hyperviseur</a></li>
<li class="toctree-l2"><a class="reference internal" href="../deploiement/route-reflector.html">VM route reflector</a></li>
</ul>
</details></li>
</ul>
<p aria-level="2" class="caption" role="heading"><span class="caption-text">Exploitation</span></p>
<ul class="nav bd-sidenav">
<li class="toctree-l1 has-children"><a class="reference internal" href="../exploitation/index.html">Exploitation</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../exploitation/configuration.html">Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exploitation/services.html">Services systemd</a></li>
<li class="toctree-l2 has-children"><a class="reference internal" href="../exploitation/api-agent/index.html">API de l’agent</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l3"><a class="reference internal" href="../exploitation/api-agent/asynchronisme.html">Modèle asynchrone et codes de retour</a></li>
<li class="toctree-l3"><a class="reference internal" href="../exploitation/api-agent/reference.html">Référence</a></li>
</ul>
</details></li>
<li class="toctree-l2"><a class="reference internal" href="../exploitation/observabilite.html">Observabilité</a></li>
<li class="toctree-l2"><a class="reference internal" href="../exploitation/diagnostic.html">Diagnostic</a></li>
</ul>
</details></li>
</ul>
<p aria-level="2" class="caption" role="heading"><span class="caption-text">Développement</span></p>
<ul class="nav bd-sidenav">
<li class="toctree-l1 has-children"><a class="reference internal" href="../developpement/index.html">Développement</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../developpement/lab.html">Lab de test multi-nœud</a></li>
</ul>
</details></li>
</ul>
<p aria-level="2" class="caption" role="heading"><span class="caption-text">Interne</span></p>
<ul class="current nav bd-sidenav">
<li class="toctree-l1 has-children"><a class="reference internal" href="../concepts/index.html">Concepts</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../concepts/vpc-subnet-vm.html">VPC, subnet et VM</a></li>
<li class="toctree-l2"><a class="reference internal" href="../concepts/modes-reseau.html">Modes réseau</a></li>
<li class="toctree-l2"><a class="reference internal" href="../concepts/cycle-de-vie.html">Cycle de vie des ressources</a></li>
<li class="toctree-l2"><a class="reference internal" href="../concepts/metadata-cloud-init.html">Metadata et cloud-init</a></li>
</ul>
</details></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../architecture/index.html">Architecture</a><details><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul>
<li class="toctree-l2"><a class="reference internal" href="../architecture/vue-densemble.html">Vue d’ensemble</a></li>
<li class="toctree-l2"><a class="reference internal" href="../architecture/stockage.html">Schéma des clés</a></li>
<li class="toctree-l2"><a class="reference internal" href="../architecture/contraintes.html">Invariants et pièges</a></li>
</ul>
</details></li>
<li class="toctree-l1 current active has-children"><a class="reference internal" href="index.html">Versions</a><details open="open"><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul class="current">
<li class="toctree-l2 current active"><a class="current reference internal" href="#">Bael</a></li>
<li class="toctree-l2"><a class="reference internal" href="0.1.0.html">Michael</a></li>
</ul>
</details></li>
</ul>
</div>
</nav></div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
<div class="sidebar-primary-item">
<div id="ethical-ad-placement"
class="flat"
data-ea-publisher="readthedocs"
data-ea-type="readthedocs-sidebar"
data-ea-manual="true">
</div></div>
</div>
</div>
<main id="main-content" class="bd-main" role="main">
<div class="sbt-scroll-pixel-helper"></div>
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article d-print-none">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item"><button class="sidebar-toggle primary-toggle btn btn-sm" title="Toggle primary sidebar" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="fa-solid fa-bars"></span>
</button></div>
</div>
<div class="header-article-items__end">
<div class="header-article-item">
<div class="article-header-buttons">
<button onclick="toggleFullScreen()"
class="btn btn-sm btn-fullscreen-button pst-navbar-icon"
title="Mode plein écran"
data-bs-placement="bottom" data-bs-toggle="tooltip"
>
<span class="btn__icon-container">
<i class="fas fa-expand"></i>
</span>
</button>
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label="Thème" data-bs-title="Thème" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light" title="Clair"></i>
<i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark" title="Sombre"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto" title="Paramètres système"></i>
</button>
<button class="btn btn-sm pst-navbar-icon search-button search-button__button pst-js-only" title="Recherche" aria-label="Recherche" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass fa-lg"></i>
</button>
<button class="sidebar-toggle secondary-toggle btn btn-sm pst-navbar-icon" title="Toggle secondary sidebar" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="fa-solid fa-list"></span>
</button>
</div></div>
</div>
</div>
</div>
<div id="jb-print-docs-body" class="onlyprint">
<h1>Bael</h1>
<!-- Table of contents -->
<div id="print-main-content">
<div id="jb-print-toc">
<div>
<h2> Contenu </h2>
</div>
<nav aria-label="Page">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#fonctionnalites">Fonctionnalités</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#correctifs">Correctifs</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#changements-internes">Changements internes</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#perimetre-et-limites-connues">Périmètre et limites connues</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mise-a-jour-depuis-la-0-1-0">Mise à jour depuis la 0.1.0</a></li>
</ul>
</nav>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<section id="bael">
<h1>Bael<a class="headerlink" href="#bael" title="Lien vers cette rubrique">#</a></h1>
<p>Serveur DHCP intégré, en coexistence avec dnsmasq, et documentation du projet.</p>
<section id="fonctionnalites">
<h2>Fonctionnalités<a class="headerlink" href="#fonctionnalites" title="Lien vers cette rubrique">#</a></h2>
<p><strong>Serveur DHCP intégré</strong></p>
<ul class="simple">
<li><p>Nouveau binaire <code class="docutils literal notranslate"><span class="pre">dhcp</span></code>, une instance par subnet lancée dans le netns du VPC par l’unit
<code class="docutils literal notranslate"><span class="pre">dhcp&#64;&lt;netns&gt;_&lt;bridge&gt;</span></code>. Il reçoit son bridge et ses deux chemins de fichiers en paramètres :
il ne compose aucun chemin et ignore le netns dans lequel il tourne</p></li>
<li><p>Piloté par l’agent sur une <strong>socket Unix</strong> <code class="docutils literal notranslate"><span class="pre">/run/two/dhcp/&lt;netns&gt;_&lt;bridge&gt;.sock</span></code>, en JSON par
ligne. Ordres idempotents en remplacement intégral : configuration du subnet à sa création,
une réservation par interface à chaque création ou suppression de VM</p></li>
<li><p><strong>Réservations statiques uniquement</strong>, pas de baux : une MAC inconnue n’obtient rien, et le
serveur reste silencieux plutôt que de répondre par un refus. Aucun <code class="docutils literal notranslate"><span class="pre">DHCPNAK</span></code> n’est émis</p></li>
<li><p>État auto-persisté dans <code class="docutils literal notranslate"><span class="pre">/run/two/dhcp/&lt;netns&gt;_&lt;bridge&gt;.state</span></code>, en écriture atomique et lisible
par le seul <code class="docutils literal notranslate"><span class="pre">root</span></code>. Le fichier appartient au processus, qui le relit à son démarrage ; l’agent
ne l’écrit jamais et se borne à le supprimer — à la création du subnet pour écarter un résidu,
à sa suppression après avoir arrêté l’unit</p></li>
<li><p>La route par défaut est décidée <strong>par interface</strong> et non plus par subnet, ce qui permet de ne
l’annoncer que sur une interface d’une VM multi-réseaux</p></li>
<li><p>L’encodage RFC 3442 de l’option 121 est délégué à <code class="docutils literal notranslate"><span class="pre">github.com/insomniacslk/dhcp</span></code></p></li>
</ul>
<p><strong>Coexistence avec dnsmasq</strong></p>
<ul class="simple">
<li><p>Nouvelle clé <code class="docutils literal notranslate"><span class="pre">dhcp.backend</span></code>, <code class="docutils literal notranslate"><span class="pre">dnsmasq</span></code> ou <code class="docutils literal notranslate"><span class="pre">two</span></code>, qui choisit le serveur des subnets <strong>créés par
cet agent</strong>. Le défaut est <code class="docutils literal notranslate"><span class="pre">dnsmasq</span></code> : un fichier de configuration de la 0.1.0, non modifié, se
comporte exactement comme avant</p></li>
<li><p>La bascule est une <strong>opération manuelle</strong> sur un hyperviseur vide — l’option ne migre rien, un
subnet déjà créé reste servi par le serveur qui l’a été. La procédure est documentée</p></li>
<li><p>Toute valeur autre que <code class="docutils literal notranslate"><span class="pre">dnsmasq</span></code> ou <code class="docutils literal notranslate"><span class="pre">two</span></code> fait échouer le démarrage de l’agent</p></li>
</ul>
<p><strong>Exploitation</strong></p>
<ul class="simple">
<li><p>Le watchdog interroge le serveur DHCP intégré et compare les réservations servies à celles que
la base implique. Il nomme ce qui diverge — ordre perdu à la création, ordre perdu à la
suppression, adresse ou route par défaut divergente — et reste en lecture seule</p></li>
<li><p>La socket de contrôle répond à <code class="docutils literal notranslate"><span class="pre">get-state</span></code> et à <code class="docutils literal notranslate"><span class="pre">probe</span></code>, ce dernier montrant sans effet de bord
ce qui serait envoyé à une MAC donnée : adresse, masque, routeur, DNS et routes</p></li>
<li><p>Documentation Sphinx du projet : concepts, architecture, déploiement et exploitation</p></li>
</ul>
</section>
<section id="correctifs">
<h2>Correctifs<a class="headerlink" href="#correctifs" title="Lien vers cette rubrique">#</a></h2>
<ul class="simple">
<li><p><strong>Un fichier de configuration présent mais invalide fait désormais échouer le démarrage.</strong>
Jusqu’en 0.1.0 l’erreur de lecture était ignorée : l’agent tournait alors entièrement sur ses
valeurs par défaut sans le dire, ce qui rendait indétectable une simple tabulation d’indentation</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">probe</span></code> annonce explicitement <code class="docutils literal notranslate"><span class="pre">&quot;served&quot;:</span> <span class="pre">false</span></code> pour une MAC non réservée, au lieu d’omettre le
champ et de le rendre indistinguable d’une réponse tronquée</p></li>
</ul>
</section>
<section id="changements-internes">
<h2>Changements internes<a class="headerlink" href="#changements-internes" title="Lien vers cette rubrique">#</a></h2>
<ul class="simple">
<li><p>Le module passe à <strong>Go 1.25</strong>, exigé par la bibliothèque DHCP retenue. La version de Go du
workflow de build, restée à 1.21 alors que le module en demandait davantage, est alignée</p></li>
<li><p>Nouveau paquet <code class="docutils literal notranslate"><span class="pre">pkg/db/statefile</span></code> : persistance générique d’un état de composant dans un
fichier, en écriture atomique. Badger a été écarté pour cet usage — une instance par subnet
coûterait une memtable de 64 Mio et quatre goroutines de compaction pour environ un kilo-octet
d’état, dans un <code class="docutils literal notranslate"><span class="pre">tmpfs</span></code>, et laisserait un verrou résiduel après un arrêt brutal</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">internal/subnet</span></code> et <code class="docutils literal notranslate"><span class="pre">internal/vm</span></code> ne parlent plus à dnsmasq en direct mais à une interface
<code class="docutils literal notranslate"><span class="pre">Backend</span></code> à deux implémentations</p></li>
</ul>
</section>
<section id="perimetre-et-limites-connues">
<h2>Périmètre et limites connues<a class="headerlink" href="#perimetre-et-limites-connues" title="Lien vers cette rubrique">#</a></h2>
<p>Celles de la 0.1.0 restent valables, sauf mention contraire ci-dessus. S’y ajoutent :</p>
<ul class="simple">
<li><p><strong>dnsmasq n’est pas retiré</strong> et reste un paquet requis : le backend intégré ne sert que les
subnets créés après la bascule, et le retour arrière suppose dnsmasq installé</p></li>
<li><p>Pas de DNS, pas de pool dynamique, pas de PXE, pas de DHCPv6 dans le serveur intégré</p></li>
<li><p>La comparaison faite par le watchdog porte sur les <strong>réservations</strong> et non sur la configuration
du subnet : celle-ci dépend de la route par défaut de l’host, dont la lecture au moment du
contrôle produirait de faux écarts. Un serveur dépourvu de configuration est en revanche signalé</p></li>
<li><p>L’option 249 (routes classless de Microsoft) n’est pas émise, comme dnsmasq ne l’émet pas</p></li>
<li><p>Le serveur intégré écoute UDP/67 sans authentification, comme tout serveur DHCP : l’isolation
entre locataires d’un même subnet repose sur les règles ebtables anti-usurpation, inchangées</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">internal/dhcpbackend</span></code> n’est testé sous Linux que pour ses appels systemd ; le reste, y compris
le dialogue avec le serveur intégré, est couvert sur toute plateforme</p></li>
</ul>
</section>
<section id="mise-a-jour-depuis-la-0-1-0">
<h2>Mise à jour depuis la 0.1.0<a class="headerlink" href="#mise-a-jour-depuis-la-0-1-0" title="Lien vers cette rubrique">#</a></h2>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>curl<span class="w"> </span>-O<span class="w"> </span>https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh
bash<span class="w"> </span>./deploy.sh<span class="w"> </span>-t<span class="w"> </span><span class="m">0</span>.2.0
</pre></div>
</div>
<p>Aucune action n’est requise : sans <code class="docutils literal notranslate"><span class="pre">dhcp.backend</span></code> dans <code class="docutils literal notranslate"><span class="pre">/etc/two/agent.yml</span></code>, le comportement est
celui de la 0.1.0. Pour passer au serveur intégré, suivre la procédure de bascule dans la
documentation d’exploitation — elle suppose un hyperviseur vidé.</p>
</section>
</section>
</article>
<footer class="prev-next-footer d-print-none">
<div class="prev-next-area">
<a class="left-prev"
href="index.html"
title="page précédente">
<i class="fa-solid fa-angle-left"></i>
<div class="prev-next-info">
<p class="prev-next-subtitle">précédent</p>
<p class="prev-next-title">Versions</p>
</div>
</a>
<a class="right-next"
href="0.1.0.html"
title="page suivante">
<div class="prev-next-info">
<p class="prev-next-subtitle">suivant</p>
<p class="prev-next-title">Michael</p>
</div>
<i class="fa-solid fa-angle-right"></i>
</a>
</div>
</footer>
</div>
<dialog id="pst-secondary-sidebar-modal"></dialog>
<div id="pst-secondary-sidebar" class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner">
<div class="sidebar-secondary-item"><div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
<i class="fa-solid fa-list"></i> Contenu
</div>
<nav id="pst-page-toc-nav" class="page-toc" aria-labelledby="pst-page-navigation-heading-2">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#fonctionnalites">Fonctionnalités</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#correctifs">Correctifs</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#changements-internes">Changements internes</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#perimetre-et-limites-connues">Périmètre et limites connues</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mise-a-jour-depuis-la-0-1-0">Mise à jour depuis la 0.1.0</a></li>
</ul>
</nav></div>
</div></div>
</div>
<footer class="bd-footer-content">
<div class="bd-footer-content__inner container">
<div class="footer-item">
<p class="component-author">
Par Nicolas Boufidjeline
</p>
</div>
<div class="footer-item">
<p class="copyright">
© Copyright 2026, Nicolas Boufidjeline.
<br/>
</p>
</div>
<div class="footer-item">
</div>
<div class="footer-item">
</div>
</div>
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script defer src="../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf"></script>
<script defer src="../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf"></script>
<footer class="bd-footer">
</footer>
</body>
</html>