diff --git a/CHANGELOG.md b/CHANGELOG.md
index f89d413..9a8177f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+## 2026-10-14 (153) — La doc du DNS rattrape les deux sites, avec ses schémas
+
+**95 preuves.** `make verifier` passe (site de Chezlepro). Documentation seulement : aucun
+rôle, gabarit ni script ne change.
+
+`docs/dns-interne.md` s'arrêtait au 2026-09-16 : un seul serveur de noms, et `technolibre.ca`
+qui « attend que `dns1.chezlepro.ca` soit publié ». Il couvre désormais l'interne et le public
+(titre « DNS : interne et public »), avec cinq schémas Mermaid, que la forge dessine :
+- **vue d'ensemble** : les primaires cachés des locataires, les deux serveurs publics, leurs
+ chemins depuis l'Internet (WAN de `bifrost-1` ; relais puis `requin`) ;
+- **le chemin d'une requête interne** : plancher, Unbound, PowerDNS sur la boucle locale,
+ résolveur du site pour un locataire neuf, `resolution_interne` ;
+- **publier une zone** (séquence) : rendu depuis le plan, NOTIFY, SOA, AXFR TSIG vers chaque
+ site, dont l'autre par le lien entre les sites ;
+- **une requête de l'Internet** (séquence) : frontière, dnsdist, PowerDNS, `reply-to` du relais ;
+- **les NS d'une zone** : `dns_public_nom` de chaque site, par le contrat, jusqu'au gabarit.
+
+Et les tableaux des flux, de ce qui se déclare et où, des gardes, et l'ordre de bascule chez
+un registraire (colle de chaque `dns1`, puis NS, puis DS).
+
+Les README de `serveur_powerdns` (de juin : ni zones publiques, ni DNSSEC, ni pairs) et de
+`serveur_dns_public` (« la réplication passera par le tunnel, plus tard » ; « rien n'est
+exposé ») sont à jour ; la page DNS du wiki y renvoie.
+
## 2026-10-14 (152) — L'administration du site de TechnoLibre, par le lien entre les sites
**95 preuves.** `make verifier` passe (site de Chezlepro), `devis_opnsense.py --verifier` est
diff --git a/docs/dns-interne.md b/docs/dns-interne.md
index 4fd0190..d83dc4a 100644
--- a/docs/dns-interne.md
+++ b/docs/dns-interne.md
@@ -1,6 +1,7 @@
-# DNS interne
+# DNS : interne et public
-> **Pour qui :** le **mainteneur** du DNS interne.
+> **Pour qui :** le **mainteneur** du DNS, et l'**exploitant** d'un site qui publie les noms
+> de ses locataires. Le nom du fichier date du temps où il ne couvrait que l'interne.
Le service DNS interne est la premiere capacite de plateforme.
@@ -10,6 +11,51 @@ Le service DNS interne est la premiere capacite de plateforme.
> que PowerDNS ne soit la). PowerDNS devient une **commodite** (zone, externe,
> dynamique), plus un point de defaillance.
+## Vue d'ensemble
+
+Deux services distincts, qui ne se parlent pas :
+
+- **la résolution interne** — chaque écosystème résout ses propres noms (`*.internal`) et
+ l'Internet pour ses machines. Rien n'en sort.
+- **le DNS public** — les zones publiques des locataires (`chezlepro.ca`, `technolibre.ca`),
+ écrites chez le locataire, servies à l'Internet par **deux sites**, sous deux noms.
+
+```mermaid
+flowchart LR
+ NET(("Internet"))
+ subgraph LOC["Les locataires — vivent au site de Chezlepro"]
+ direction TB
+ P1["infra-dns-01 · OPS-Chezlepro · 10.17.19.11
pdns@public :5300
primaire caché, signe DNSSEC"]
+ P2["infra-dns-01 · OPS-Technolibre · 10.23.19.11
pdns@public :5300
primaire caché, signe DNSSEC"]
+ end
+ subgraph SC["Site de Chezlepro"]
+ direction TB
+ BIF["bifrost-1
WAN 69.70.26.62:53"]
+ S1["site-dnspub-01 · 10.37.37.21
dnsdist :1053 → PowerDNS :53
dns1.chezlepro.ca"]
+ BIF -- "redirection :1053" --> S1
+ end
+ subgraph ST["Site de TechnoLibre"]
+ direction TB
+ REL["relais · VPS OVH
51.79.45.193"]
+ REQ["requin
opt9 RELAIS · opt10 lien"]
+ S2["site-dnspub-01 · 10.31.37.21
dnsdist :1053 → PowerDNS :53
dns1.technolibre.ca"]
+ REL -- "tunnel WireGuard" --> REQ
+ REQ -- "redirection :1053" --> S2
+ end
+ P1 & P2 -- "NOTIFY · AXFR signé TSIG" --> S1
+ P1 & P2 -. "NOTIFY · AXFR signé TSIG
par le lien entre les sites" .-> S2
+ NET -- "53" --> BIF
+ NET -- "53" --> REL
+```
+
+| Pièce | Rôle | Où | Section |
+|---|---|---|---|
+| plancher `/etc/hosts` | résout la flotte, DNS éteint | chaque VM | [Trois couches](#trois-couches-et-une-seule-est-optionnelle) |
+| Unbound | LE résolveur d'un écosystème | `infra-dns-01` (locataire), `site-dns-01` (site) | idem |
+| PowerDNS principal | autorité sur la zone `.internal` | boucle locale, derrière Unbound | idem |
+| PowerDNS `pdns@public` | primaire caché des zones publiques | `infra-dns-01` du locataire, `:5300` | [Zones publiques](#zones-publiques) |
+| PowerDNS + dnsdist | serveur de noms public du site, secondaire | `site-dnspub-01` de chaque site | [Deux sites](#deux-sites-deux-serveurs-de-noms) |
+
## Trois couches, et une seule est optionnelle
> **Ce paragraphe decrivait le modele d'avant le 2026-08-24** — un Unbound *sur chaque VM*,
@@ -36,6 +82,31 @@ lui-meme. L'ancien nom (`client_unbound`) mentait des lors qu'il n'installait pl
l'ecosysteme garde la resolution d'amorcage de cloud-init. C'est un choix valide, pas une
panne.
+### Le chemin d'une requête interne
+
+```mermaid
+flowchart TB
+ Q["Une machine du locataire
cherche un nom"] --> H{"/etc/hosts
le plancher"}
+ H -- "machine de la flotte" --> A1["adresse — sans DNS"]
+ H -- "autre nom" --> U["Unbound · infra-dns-01:53
serveur_resolveur"]
+ U -- "*.internal et zone inverse
stub-zone" --> PA["PowerDNS principal
127.0.0.1:5300"]
+ U -- "tout le reste
récursion depuis la racine" --> NET(("Internet"))
+ Q -. "locataire neuf, sans résolveur à lui" .-> SD["site-dns-01
le résolveur du site
serveur_resolveur_site"]
+```
+
+- **Le résolveur est la seule porte.** Quand PowerDNS partage l'hôte d'Unbound, il écoute
+ sur la boucle locale (`5300`) : personne ne l'interroge directement (port `derive`,
+ `roles/serveur_powerdns/meta/flux.yml`).
+- **Le site prête ses noms aux locataires neufs.** Tant qu'un locataire n'a pas son
+ résolveur, `client_resolveur` le fait interroger celui du site (`serveur_resolveur_site`,
+ dont la liste d'autorisation se dérive des locataires hébergés), puis le bascule chez lui.
+- **Où mène un nom exposé, vu de l'intérieur** : `resolution_interne` dans
+ `plan/domaines.yml`. `service` (le site) : la zone mène au service lui-même — l'edge est
+ pour les personnes. `edge` (défaut, les locataires) : la machine passe par l'edge, parce
+ que certains services n'existent en HTTPS que derrière lui (Keycloak).
+- **Une machine qui naît** interroge `dns_amorcage` (la patte de la frontière) tant que le
+ résolveur de son site n'existe pas.
+
## Groupes
```text
@@ -196,9 +267,13 @@ publiquement, et il en faut **deux** (exigence du registre `.ca`). Une mesure qu
« mesure impossible », jamais « absent ». Sa limite est écrite à chaque rapport : sans
transfert de zone, un export chez le fournisseur actuel reste la seule preuve d'exhaustivité.
-Au 2026-09-16 : `chezlepro.ca` reproduit la production (rien ne serait perdu) ;
-`technolibre.ca` est **préparée, pas basculée** — la décision revient au responsable désigné
-de TechnoLibre, et elle attend que `dns1.chezlepro.ca` soit publié.
+Le devis sonde aussi **la colle de chaque serveur désigné** — ceux du site et ceux des pairs
+([Deux sites](#deux-sites-deux-serveurs-de-noms)).
+
+Au 2026-10-14 : les deux zones sont servies par les deux sites, signées, au même serial ;
+**aucune n'est basculée chez son registraire**. `chezlepro.ca` reproduit la production
+(rien ne serait perdu). La décision pour `technolibre.ca` revient au responsable désigné de
+TechnoLibre.
### Signature DNSSEC : le locataire signe, avec la clé de sa voûte
@@ -239,3 +314,147 @@ La sonde `zones-publiques` du site alerte sur une zone signée servie **nue**, a
**Ordre de la mise en service** : basculer les serveurs de noms (zone signée, sans DS : le
domaine reste « non sécurisé », pas cassé), vérifier, **puis** remettre le DS au registraire.
Jamais l'inverse.
+
+## Deux sites, deux serveurs de noms
+
+> Ajouté le 2026-10-14. Le registre des `.ca` exige deux serveurs de noms ; deux serveurs
+> sur le même réseau tomberaient ensemble. Le second est au site de TechnoLibre, tenu par une
+> autre organisation, sur un autre réseau.
+
+**Chaque site sert les zones publiques de tous les locataires qu'il connaît : les siens, et
+ceux de son pair.** Les deux serveurs sont **secondaires** l'un comme l'autre, et tirent
+chacun la zone **directement du primaire du locataire** — jamais l'un de l'autre
+(`disable-axfr=yes` au site). Un site qui tombe n'emporte donc pas la copie de l'autre.
+
+| Site | Serveur | Nom public | Adresse publique | Chemin depuis l'Internet |
+|---|---|---|---|---|
+| Chezlepro | `site-dnspub-01` · `10.37.37.21` | `dns1.chezlepro.ca` | `69.70.26.62` | WAN de `bifrost-1` → `:1053` |
+| TechnoLibre | `site-dnspub-01` · `10.31.37.21` | `dns1.technolibre.ca` | `51.79.45.193` | relais (VPS) → tunnel `opt9` de `requin` → `:1053` |
+
+### Publier une zone
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant X as Exploitant du locataire
+ participant P as pdns@public
infra-dns-01 du locataire
+ participant C as site-dnspub-01
site de Chezlepro
+ participant T as site-dnspub-01
site de TechnoLibre
+ X->>P: rôle serveur_powerdns — la zone est rendue depuis le plan
+ Note over P: SOA et NS = dns1 du site + dns1 de chaque pair
serial = suit le contenu · signée avec la clé de la voûte
+ P-)C: NOTIFY (only-notify : les seuls serveurs du contrat)
+ P-)T: NOTIFY, par le lien entre les sites
+ C->>P: SOA ? (UDP 5300)
+ C->>P: AXFR signé TSIG (TCP 5300)
+ P-->>C: zone déjà signée — servie telle quelle (PRESIGNED)
+ T->>P: SOA ? puis AXFR signé TSIG, par le lien
+ P-->>T: zone déjà signée
+```
+
+- **Le locataire écrit, les sites servent.** Les deux sites ne détiennent ni la zone en
+ source, ni la clé DNSSEC.
+- **`only-notify` et `also-notify`** bornent les notifications aux adresses du contrat du
+ site (`dns_public_site` et `dns_public_pairs`). Sans eux, le primaire notifierait les
+ adresses publiques de ses NS, depuis l'intérieur du locataire.
+- **Le transfert passe par le lien** quand le secondaire est sur l'autre site : la frontière
+ du site où vit le locataire laisse entrer le transfert et sortir les NOTIFY ; celle du site
+ qui réplique pose une route `/32` vers chaque primaire. Le devis les dérive de la fiche que
+ porte chaque locataire (où il vit), et P24 juge ces routes à part.
+
+### Une requête de l'Internet
+
+```mermaid
+sequenceDiagram
+ participant R as Résolveur sur Internet
+ participant F as Frontière
bifrost-1 ou requin
+ participant D as dnsdist :1053
+ participant A as PowerDNS :53
+ R->>F: chezlepro.ca MX ? (port 53)
+ Note over F: TechnoLibre : arrive par le relais et le tunnel opt9,
et repart par lui (reply-to RELAIS_GW)
+ F->>D: redirection vers :1053
+ Note over D: refuse NOTIFY, UPDATE, AXFR · tronque ANY en UDP
débit borné par /24
+ D->>A: requête admise
+ A-->>D: réponse signée
+ D-->>R: réponse
+```
+
+**Sans `reply-to`, la réponse du site de TechnoLibre se perdrait** : elle repartirait par la
+route par défaut, le WAN, qui n'a qu'une adresse privée en amont (mesuré le 2026-10-13).
+
+### Les flux
+
+| Flux | De | Vers | Port | Chemin |
+|---|---|---|---|---|
+| Requête publique | Internet | dnsdist du site | 53 → 1053, UDP et TCP | redirection de la frontière ; par le relais au site de TechnoLibre |
+| Requête admise | dnsdist | PowerDNS du site | 53, boucle de l'hôte | local |
+| NOTIFY | `pdns@public` du locataire | PowerDNS de chaque site | 53/UDP | local ; par le lien vers l'autre site |
+| SOA, puis AXFR TSIG | PowerDNS de chaque site | `pdns@public` du locataire | 5300, UDP puis TCP | local ; par le lien depuis l'autre site |
+| Résolution interne | machine du locataire | Unbound de son écosystème | 53 | dans l'écosystème |
+| Zone `.internal` | Unbound | PowerDNS principal | 5300, boucle locale | local |
+| Récursion | Unbound | Internet | 53 | sortie de la frontière |
+
+Ces flux sont déclarés par les rôles (`meta/flux.yml` de `serveur_dns_public`,
+`serveur_powerdns`, `serveur_resolveur`) et par le lien (`opnsense_liens_sites`) ; le devis
+de la frontière et le pare-feu Proxmox en dérivent leurs règles. Aucun n'est écrit à la
+main sur une frontière.
+
+### Ce qui se déclare, et où
+
+| Clé | Fichier | Ce qu'elle décide |
+|---|---|---|
+| `autorite: primaire-cache`, `dnssec`, `enregistrements` | `plan/domaines.yml` du **locataire** | la zone est publique, signée, et ce qu'elle porte |
+| `dns_public_nom` | `plan/10-intrants.yml` du **site** | le nom de SON serveur de noms (`dns1.`) |
+| `dns_public_pairs` | plan du **site**, des deux côtés | le site pair qui réplique ; `inactif` n'émet rien |
+| `opnsense_liens_sites` | `opnsense.yml` du **site** | le tunnel que prennent NOTIFY et transferts |
+| `opnsense_wan_ip` | `opnsense.yml` du **site** | l'adresse publique de son serveur de noms |
+
+Le **contrat du site** (`make site-intrants`) en tire, pour chaque locataire, ce qu'il
+dépose dans sa fiche (`fiche-site.yml`) : `dns_public_site`, `dns_public_pairs`,
+`dns_public_nom` et `dns_public_noms_pairs` (le nom et l'adresse publique du serveur de
+chaque pair, lus dans **son** plan et **sa** carte, par les mêmes fonctions que pour le site
+lui-même).
+
+### Les NS d'une zone
+
+```mermaid
+flowchart LR
+ PC["plan du site de Chezlepro
dns_public_nom: dns1.chezlepro.ca"] --> K["contrat du site
fiche du locataire"]
+ PT["plan du site de TechnoLibre
dns_public_nom: dns1.technolibre.ca
+ opnsense_wan_ip"] -- "dns_public_noms_pairs" --> K
+ K --> Z["zone-publique.db.j2
chez le locataire"]
+ Z --> NS["chezlepro.ca — NS dns1.chezlepro.ca, NS dns1.technolibre.ca
A de dns1.chezlepro.ca : seulement dans chezlepro.ca
A de dns1.technolibre.ca : seulement dans technolibre.ca"]
+```
+
+- **Un site, un nom** : `dns1` sous le domaine de l'organisation qui tient le site. Pas
+ `ns1`/`ns2`, qui existent en production à d'autres adresses.
+- **Seule la zone qui contient un nom en porte le A**, à l'adresse publique de **son** site.
+ Les autres zones ne le désignent que par son nom.
+- **Sans pair, le rendu est identique octet pour octet** à celui d'un site seul.
+
+### Les gardes
+
+| Garde | Où | Ce qu'elle refuse |
+|---|---|---|
+| relation des deux côtés | P82 (`prouver._dns_paires`) | un pair déclaré d'un seul côté — le second serveur serait vide sans que personne le voie |
+| un pair nomme son serveur | P82 (`prouver._dns_paires`) | un pair actif sans `dns_public_nom` — ses zones n'en désigneraient qu'un, alors qu'il les sert |
+| signé avant exposé | P82 | exposer un serveur public dont une zone n'est pas signée |
+| nom et adresse du pair | `serveur_powerdns` (`zones-publiques.yml`) | un nom mal formé, une adresse privée, un nom égal au nôtre, un nom redéclaré |
+| contrat déposé | `make site-intrants-verifier` | une fiche de locataire qui diffère du contrat (une adresse faussée la rend NON CONFORME) |
+| routes du lien | P24 | une route `/32` qu'aucune règle du lien n'utilise |
+| zone servie nue | sonde `zones-publiques` | une zone signée servie sans signature ; signatures sous 6 jours (avertit), sous 3 (alerte) |
+
+### Basculer chez un registraire
+
+L'ordre, pour chaque domaine :
+
+1. **`make dns-bascule-devis`** — rien ne serait perdu, et chaque serveur désigné résout déjà
+ publiquement.
+2. **La colle** chez le registraire du domaine qui contient le nom : `dns1.chezlepro.ca`
+ chez celui de `chezlepro.ca`, `dns1.technolibre.ca` chez celui de `technolibre.ca`.
+3. **Les deux NS** chez le registraire de la zone basculée. Zone signée, sans DS : le domaine
+ reste « non sécurisé », pas cassé.
+4. **Vérifier** depuis l'Internet, sur les deux adresses.
+5. **Puis seulement le DS** (`make dnssec-ds`). Jamais l'inverse.
+
+**État au 2026-10-14** : les deux sites servent `chezlepro.ca` et `technolibre.ca` au même
+serial, chacune avec deux NS signés. **Ni la colle ni les NS ne sont encore chez les
+registraires.**
diff --git a/roles/serveur_dns_public/README.md b/roles/serveur_dns_public/README.md
index 9f07aed..de15490 100644
--- a/roles/serveur_dns_public/README.md
+++ b/roles/serveur_dns_public/README.md
@@ -10,8 +10,9 @@ site la sert.
```
LOCATAIRE infra-dns-01 primaire caché de chezlepro.ca ─┐ NOTIFY
- (autorite: primaire-cache) │ AXFR signé TSIG, tiré par le site
-SITE site-dnspub-01 secondaire public ◄──────────────┘
+ (autorite: primaire-cache) │ AXFR signé TSIG, tiré par chaque site
+SITE site-dnspub-01 secondaire public ◄──────────────┤
+SITE PAIR site-dnspub-01 secondaire public ◄──────────────┘ par le lien entre les sites
```
- **Le primaire reste chez le locataire.** Quand il part, il emporte sa zone, et le site
@@ -37,8 +38,9 @@ Deux instances jetables, sept vérifications, avant d'écrire une ligne de ce r
## Durcissement
- **Secondaire seulement** : `secondary=yes`, `primary=no`.
-- **Aucun transfert sortant** en phase 1 (`disable-axfr=yes`). La réplication vers le
- site pair passera par le tunnel WireGuard, plus tard.
+- **Aucun transfert sortant** (`disable-axfr=yes`). Le site pair ne copie pas ce serveur :
+ il tire chaque zone **du primaire du locataire**, par le lien entre les sites (2026-10-14).
+ Un site qui tombe n'emporte pas la copie de l'autre.
- **Notifications acceptées des seuls primaires déclarés.**
- **`version-string=anonymous`** : la version est la première chose qu'un balayage demande.
- **`security-poll-suffix=`** vide : PowerDNS interroge par défaut un domaine de l'éditeur
@@ -46,12 +48,18 @@ Deux instances jetables, sept vérifications, avant d'écrire une ligne de ce r
- **Pas de récursion** : PowerDNS Authoritative ne récurse pas — vérifié, il répond
`REFUSED`.
-## Ce que la phase 1 n'expose pas
+## Exposé à l'Internet (phase 2)
-**Aucun flux depuis Internet.** Le port 53 public viendra en phase 2, par la redirection
-de la frontière — et seulement après DNSSEC signé chez le locataire, CAA, et la limitation
-de débit des réponses. Le déclarer aujourd'hui dans `meta/flux.yml` ferait émettre au
-devis une règle sur le WAN que personne n'aurait décidée.
+Le 53 public arrive par la redirection de la frontière vers le frontal (`dnsdist`, `1053`),
+après DNSSEC signé chez le locataire, CAA, et la limitation de débit — P82 refuse l'inverse.
+Au site de TechnoLibre, il arrive par le relais et le tunnel `opt9` de `requin`.
+
+## Deux sites, deux serveurs
+
+`dns_public_pairs` (plan du site, déclaré des deux côtés) fait de chaque site le second
+serveur de noms de l'autre. Chaque zone désigne les deux (`dns1.chezlepro.ca`,
+`dns1.technolibre.ca`). Schémas, flux et ordre de bascule : `docs/dns-interne.md`, section
+« Deux sites, deux serveurs de noms ».
## Le frontal public : dnsdist (2026-09-16, phase 2)
diff --git a/roles/serveur_powerdns/README.md b/roles/serveur_powerdns/README.md
index f346cd3..785edee 100644
--- a/roles/serveur_powerdns/README.md
+++ b/roles/serveur_powerdns/README.md
@@ -1,17 +1,62 @@
-# Role `serveur_powerdns`
+# Rôle `serveur_powerdns`
-Installe et configure PowerDNS Authoritative comme service DNS interne initial.
+> **Pour qui :** le mainteneur du DNS d'un écosystème. La vue d'ensemble, avec ses schémas,
+> est dans `docs/dns-interne.md`.
-Ce premier jalon utilise le backend BIND et une zone generee par Ansible depuis
-l'inventaire. Cela evite de rendre DNS dependant de PostgreSQL avant que le
-service `serveur_postgresql` soit disponible.
+PowerDNS Authoritative, backend BIND, zones générées par Ansible depuis l'inventaire et le
+plan. Pas de dépendance à PostgreSQL. Le rôle porte **deux instances**, qui ne se voient pas.
-Variables principales :
+| Instance | Ce qu'elle sert | Écoute | Qui l'interroge |
+|---|---|---|---|
+| `pdns` (principale) | la zone interne (`.internal`) et ses zones inverses | `5300` sur la boucle locale quand le résolveur partage l'hôte, `53` sinon (port `derive`) | le résolveur de l'écosystème, seul |
+| `pdns@public` | les zones `autorite: primaire-cache` du plan — primaire **caché** | `:5300` | le serveur DNS public de chaque site, en TSIG |
-- `serveur_powerdns_zone`
-- `serveur_powerdns_nameserver`
-- `serveur_powerdns_contact`
-- `serveur_powerdns_records`
+**Une instance à part pour le public** : faire écouter la principale sur l'adresse de l'hôte
+aurait permis au serveur public du site d'interroger la zone `.internal`.
-Les hotes actifs portant `ansible_host` sont ajoutes automatiquement dans la
-zone par le template.
+## La zone interne
+
+- Chaque hôte actif qui porte `ansible_host` reçoit son A, sans déclaration.
+- Les noms exposés (`serveur_powerdns_expositions`) mènent au service ou à l'edge selon
+ `resolution_interne` du domaine.
+- Les enregistrements en plus : `serveur_powerdns_records`.
+
+## Les zones publiques (`tasks/zones-publiques.yml`)
+
+Joué seulement là où le site a un serveur public à servir (`dns_public_site` non vide).
+
+- **SOA et NS** : le serveur du site (`serveur_powerdns_dns_public_nom`) **et celui de
+ chaque pair** (`serveur_powerdns_dns_public_noms_pairs`). Seule la zone qui contient un de
+ ces noms en porte le A, à l'adresse publique de son site. Sans pair, le rendu est identique
+ octet pour octet.
+- **Enregistrements** : ceux du plan (`plan/domaines.yml`), déjà passés au crible par
+ `valider_domaines`.
+- **Le serial suit le contenu**, et l'état DNSSEC fait partie du contenu.
+- **DNSSEC** : une clé CSK par zone, tenue dans la voûte du locataire
+ (`vault_dnssec_`), jamais créée sur la machine. Servie à l'heure (`SOA-EDIT EPOCH`).
+- **Transfert** : TSIG seul l'ouvre (`allow-axfr-ips` ne garde que la boucle locale, parce
+ qu'une adresse listée obtiendrait la zone sans signature).
+- **Notifications** : `only-notify` et `also-notify` limités à `dns_public_site` et
+ `dns_public_pairs` — les adresses que le contrat du site dépose dans la fiche.
+- **Gardes** : nom de pair bien formé, adresse publique, distinct du nôtre, jamais
+ redéclaré.
+
+## Variables
+
+Celles qu'on règle, les autres se dérivent :
+
+| Variable | Défaut | Source |
+|---|---|---|
+| `serveur_powerdns_zone` | `domaine_interne` | plan |
+| `serveur_powerdns_records` | `[]` | inventaire |
+| `serveur_powerdns_dns_public_site` | `dns_public_site` | contrat du site |
+| `serveur_powerdns_dns_public_pairs` | `dns_public_pairs` | contrat du site |
+| `serveur_powerdns_dns_public_nom` | `dns_public_nom` | contrat du site |
+| `serveur_powerdns_dns_public_noms_pairs` | `dns_public_noms_pairs` | contrat du site |
+| `serveur_powerdns_public_port` | `5300` | — |
+
+## Flux
+
+`meta/flux.yml` : l'entrée de la zone interne (port `derive`), la résolution sortante de
+l'autoritatif pour ses propres besoins (il est exempté de `client_resolveur`), et l'entrée
+`5300` UDP/TCP depuis le serveur public du site, seulement là où `pdns@public` existe.
diff --git a/wiki/DNS-et-résolution.md b/wiki/DNS-et-résolution.md
index 273f32f..2fe0bb1 100644
--- a/wiki/DNS-et-résolution.md
+++ b/wiki/DNS-et-résolution.md
@@ -87,4 +87,5 @@ Tu as appris **la hiérarchie de résolution** (hosts → récursif → autorita
## Pour aller plus loin *(dépôt)*
- Rôles : `roles/hosts_statiques` (le plancher), `roles/serveur_powerdns`, `roles/client_resolveur`.
- Conception des 3 couches + frontière publique : `docs/dns-interne.md`.
+- Le DNS **public** — le locataire écrit sa zone, deux sites la servent (`dns1.chezlepro.ca`, `dns1.technolibre.ca`) : schémas des processus et des flux dans `docs/dns-interne.md`, et `roles/serveur_dns_public`.
- Note : `client_resolveur` est une **intégration universelle** (elle suit l'existence de `serveur_resolveur`) — voir l'unité *Liaisons* et `docs/integrations-vm.md`.