> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oximail.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# La fédération entre organisations

> Deux serveurs OxiMail tenus par deux organisations, appairés hors bande : le modèle de confiance (racines d'identité, clé de travail, requêtes signées, transport épinglé), la cérémonie d'appairage, l'enregistrement _jmap-federation._tcp, le temps occupé d'une organisation à l'autre, les dossiers du Drive partagés en lecture et les comptes miroirs qui les montrent, la section [federation], les lignes doctor et ce qui n'est pas servi.

La fédération permet à deux serveurs OxiMail, tenus chacun par une **organisation différente**, de se répondre directement : aucun hub au milieu, aucun compte invité, aucun annuaire partagé. Elle sert aujourd'hui deux choses, toutes deux en lecture seule :

* **Le temps occupé d'une organisation à l'autre.** Chercher un créneau avec quelqu'un d'une organisation appairée lit son libre/occupé sur son propre serveur. À l'inverse, une organisation appairée peut lire le temps occupé de vos personnes, chacune sous son propre consentement.
* **Des dossiers du Drive partagés avec une organisation appairée.** L'exploitant du propriétaire partage un dossier ou un fichier en lecture. L'autre côté le montre, en lecture seule, dans un **compte miroir** de son propre Drive.

La fédération est **désactivée par défaut**. Un serveur qui ne fédère jamais ne détient aucune clé de fédération, ne monte aucune route et répond exactement comme un serveur sans cette fonction. Tout ce que décrit cette page vaut par organisation (tenant) : une box qui héberge plusieurs organisations les appaire chacune séparément, sous son propre realm.

<Note>
  Le transport fédéré est récent (octobre 2026) et volontairement étroit : deux chemins de lecture, ouverts par les administrateurs des deux côtés, jamais par découverte. Le dépôt de courrier entre serveurs, les salons de chat fédérés et l'écriture dans un dossier partagé sont spécifiés dans les [brouillons](../reference/ietf-drafts) et **ne sont pas servis**. Voir [ce qui n'est pas servi](#ce-qui-nest-pas-servi).
</Note>

## Le modèle de confiance

Trois décisions façonnent tout le reste. Chacune existe parce que l'autre option laisserait quelqu'un d'autre que les deux administrateurs décider qui est digne de confiance.

**L'appairage lie deux organisations et se décide hors bande.** Un appairage nomme un **realm** (le domaine de l'organisation, `partner.example`). Il est écrit par une cérémonie d'exploitant de chaque côté, après que les deux administrateurs ont comparé leurs empreintes de vive voix. Il n'existe pas de « découvrir puis accepter » : une cérémonie qui fait confiance au premier qui répond ne vaut rien. Le DNS ne fait jamais parler ce serveur à un serveur avec lequel il n'est pas appairé.

**L'identité a deux moitiés.** Ce qu'un pair épingle, ce sont les **racines d'identité** de l'organisation : de deux à cinq clés *sœurs* (trois par défaut), chacune mise sous séquestre sous sa propre **clé papier**, détenue par l'organisation (un coffre, un associé, un second bureau). Le serveur seul ne peut jamais les reconstituer. Ce qui signe les requêtes, c'est une **clé de travail** sur la box, certifiée par une racine pour une fenêtre de validité (365 jours par défaut). Faire tourner la clé de travail ne demande rien à aucun pair : ils ont épinglé les racines, et les racines se portent garantes de la suivante. Chaque clé de travail porte une **époque** qui ne fait que croître. Elle vaut la plus grande de deux valeurs : l'époque précédente plus un, ou l'horloge en secondes. Une rotation est donc une révocation, et une base restaurée depuis un état plus ancien ne réemploie jamais une époque que les pairs ont déjà vue. Un pair qui réémet une époque sous une autre clé (ou un identifiant de clé connu lié à une autre clé) est refusé.

**Chaque requête et chaque réponse est signée, sur du HTTPS ordinaire.** Une requête fédérée va au point d'entrée `/jmap/federation` du pair, sur son port HTTPS habituel. Elle est signée selon le profil RFC 9421 du brouillon de fédération : elle nomme les deux realms, porte son nonce dans le champ d'en-tête `JMAP-Federation` et le certificat de la clé de travail dans `JMAP-Federation-Certificate`. Elle est vérifiée sur ses champs d'en-tête (profil, fraîcheur, appairage, certificat contre les racines épinglées, signature, nonce, époque) **avant** qu'un seul octet de son contenu soit lu ; le contenu est plafonné à 64 Kio. Le certificat voyage avec la requête : aucune requête ne fait donc aller chercher des clés au serveur qui la reçoit. Une requête créée avant le démarrage du processus qui la reçoit est refusée, ce qui ferme le rejeu à travers un redémarrage. Les réponses sont signées de la même façon, et vérifiées avant qu'on en utilise la moindre partie. Les épingles TLS enregistrées à l'appairage sont contrôlées pendant la poignée de main, **en plus** de la validation ordinaire du certificat, jamais à sa place.

### Trois niveaux, jamais confondus

| Niveau | Décidé par | Dit |
| - | - | - |
| **Appairage** | les administrateurs, des deux côtés | « nos deux serveurs se parlent » |
| **Grant** (disponibilité) | la personne concernée, et elle seule | « vous pouvez demander *mon* temps occupé » |
| **Partage de nœud** (Drive) | l'exploitant de l'organisation propriétaire | « vous pouvez lire *ce* dossier » |

Un grant élargit **qui** peut demander, jamais **ce** qui est vu : il n'atteint que les agendas que la personne compte déjà dans sa disponibilité, et la réponse porte des périodes occupées, jamais un événement. Un partage de nœud ouvre un dossier ou un fichier et tout ce qui se trouve en dessous, jamais ce qui est à côté ou au-dessus. Ni l'un ni l'autre ne crée de principal local pour le pair : le pair ne devient jamais membre, lecteur ou groupe de cette box.

Le grain est l'**organisation**. Une requête fédérée prouve quel *serveur* demande, pas laquelle de ses personnes a agi. Un grant qui nommerait une personne à l'autre bout n'aurait donc que l'air d'être plus étroit. La conséquence se dit telle quelle : l'exploitant de l'autre organisation peut lire ce qui est partagé avec cette organisation, et `federation shares add` le dit dans sa simulation. Le côté JMAP des grants et des divulgations est décrit sur la [page du partage](../developer/jmap-sharing#dune-organisation-à-lautre-la-fédération).

### La juridiction

Chaque côté enregistre la **juridiction** de l'autre, un code pays ISO 3166-1 alpha-2 (`CH`, `DE`, `FR`), saisi à l'appairage et figé dans chaque grant accordé à cette organisation : le consentement a été donné à une contrepartie située quelque part. Votre propre juridiction est le **pays d'établissement déclaré** de l'organisation (`oximail tenant identity set --tenant <id> --establishment-country CH --apply`), sinon celui hérité de l'opérateur d'instance. `federation identity` le lit à voix haute à côté des empreintes, `federation pair` enregistre ce qu'il a déclaré à chaque pair, et `doctor` avertit quand le pays déclaré aujourd'hui diffère de ce qu'un pair s'est vu dire ([lignes doctor](#lignes-doctor-et-métriques)).

### Ce qui quitte la box, et ce qui n'en sort pas

La liste des organisations avec lesquelles vous êtes appairé regarde l'organisation. Chaque ligne de fédération de `oximail doctor` **compte** les appairages et les partages et **ne nomme jamais un realm**, et aucune métrique de fédération ne porte d'étiquette de pair : la ronde et les métriques quittent la box pour la supervision. `oximail federation peers list` et `oximail federation shares list` les nomment, sur la box. La porte a sa propre [classe de bannissement](./anti-spam#anti-abus-limitation-de-débit-et-fail2ban) : un échec de fédération ne bannit pas une adresse pour le courrier et le web, ni l'inverse.

## Avant d'appairer

1. **Ouvrez la porte** dans la section `[federation]` ([configuration](#configuration)), avec l'URL à laquelle les pairs joindront ce serveur. Son chemin doit être `/jmap/federation`, et un proxy inverse placé devant doit livrer ce chemin sans le modifier : le pair le signe.
2. **Déclarez le pays d'établissement** de l'organisation, pour que l'autre côté ait une juridiction à enregistrer pour vous.
3. **Publiez l'enregistrement de fédération** dans le DNS une fois la porte ouverte ([plus bas](#lenregistrement-dns)). Il sert au temps occupé ; les chemins du Drive utilisent le point d'entrée enregistré à l'appairage.

Le serveur refuse de démarrer (code de sortie `2`) avec `enabled = true` sans point d'entrée au chemin de la porte, et quand l'adresse enregistrée d'un pair se trouve dans `[security] trusted_ips` : les adresses de confiance contournent le limiteur de débit et le compteur de bannissement qui protègent la porte.

## Appairer deux organisations

Les deux administrateurs suivent les mêmes étapes, chacun sur son serveur, l'autre au téléphone. Chaque verbe est une simulation tant que `--yes` n'est pas passé.

<Steps>
  <Step title="Créer l'identité (une fois par organisation)">
    ```bash theme={null}
    oximail federation identity --tenant <id> --realm example.com --custody "coffre,tiroir du bureau,associé"
    ```

    La première exécution est toute la cérémonie en une commande : elle crée le jeu de racines (`--roots`, de 2 à 5, trois par défaut ; une seule est refusée, car une racine unique est un point de défaillance unique), met chaque racine sous séquestre sous sa propre clé papier, affiche ces clés papier **une seule fois**, et certifie une clé de travail (`--valid-days`, 365 par défaut). `--custody` est obligatoire : une étiquette par racine, pour qu'on puisse dire plus tard où se trouve chaque sœur. Le realm ne peut plus changer ensuite : cela réancrerait chaque pair.
  </Step>

  <Step title="Lire vos empreintes à l'autre administrateur">
    ```bash theme={null}
    oximail federation identity --tenant <id>
    ```

    La commande affiche une **empreinte de racine** par sœur (calculée sur le realm et la racine : la confirmer, c'est s'accorder sur les deux), votre juridiction, et l'**empreinte de transport** : le realm, le point d'entrée, la méthode, la source de clé, le rôle et les épingles TLS triées de votre section `[federation]`. Lisez-les ; notez les siennes.
  </Step>

  <Step title="Simuler l'appairage">
    ```bash theme={null}
    oximail federation pair --tenant <id> --realm partner.example \
      --key ed25519:<racine-1> --key ed25519:<racine-2> --key ed25519:<racine-3> \
      --jurisdiction DE \
      --endpoint https://mail.partner.example/jmap/federation \
      --tls-pin sha256/<épingle>
    ```

    Passez chaque racine qu'il a lue (`--key` se répète : n'épingler qu'une sœur ferait casser l'appairage au premier remplacement de sœur). La simulation rapporte des faits : s'il existe déjà un appairage, si chaque clé figure déjà dans le jeu inscrit de ce realm, les grants qui nomment ce realm, chaque empreinte de racine et l'empreinte de transport à comparer. `--tls-pin` se répète (la clé en service et la suivante, quatre au plus) ; sans épingle, le certificat du pair est validé comme d'habitude et rien n'est épinglé. On n'omet `--endpoint` que pour un pair que ce serveur n'appelle jamais.
  </Step>

  <Step title="Confirmer les deux valeurs, puis épingler">
    ```bash theme={null}
    oximail federation pair --tenant <id> --realm partner.example \
      --key ed25519:<racine-1> --key ed25519:<racine-2> --key ed25519:<racine-3> \
      --jurisdiction DE --endpoint https://mail.partner.example/jmap/federation \
      --tls-pin sha256/<épingle> --transport-fingerprint <empreinte lue par l'autre> --yes
    ```

    `--yes` est refusé sans `--transport-fingerprint`, ou avec une valeur qui ne correspond pas. Les lignes de racine couvrent les clés ; la ligne de transport couvre le point d'entrée, les épingles et la façon dont le pair s'authentifie. Une cérémonie qui n'aurait comparé que l'une des deux laisserait substituer l'autre. Rien n'est écrit en cas de refus.
  </Step>

  <Step title="Vérifier">
    ```bash theme={null}
    oximail federation peers list
    oximail doctor
    ```

    `peers list` montre chaque appairage avec son état et le transport qu'il a enregistré. Dès que les deux côtés ont épinglé, l'appairage sert.
  </Step>
</Steps>

**Un tunnel posé par vous.** Si les deux sites sont reliés par un tunnel que vous exploitez, `--address <ip>` enregistre une adresse privée littérale (ou partagée, `100.64.0.0/10`) pour joindre l'hôte de ce pair, et de ce pair seulement. Ce n'est jamais une plage, jamais une adresse de `trusted_ips`, et elle ne fait pas partie de l'empreinte de transport : c'est votre routage, que l'autre côté ne connaît pas. TLS vérifie toujours le nom du point d'entrée. Aucun tunnel n'est intégré au serveur, et aucun n'est nécessaire quand les deux sites ont une adresse publique.

**Quand l'appairage change.** `federation peers unpair --realm … --yes` **suspend** un appairage, il ne le supprime jamais : les grants qui nomment cette organisation cessent d'autoriser tant qu'il dort, et restent la décision de leurs sujets. `peers suspend --cause …` nomme le fait qui manque (`admin-unpaired`, `key-mismatch`, `anchor-unconfirmed`, `restore-unconfirmed`), car la cause décide de l'acte qui la lève ; `peers resume` ne lève qu'une rupture administrative. Une clé discordante ou une ancre non confirmée (après une restauration de base, ou pour un appairage antérieur au modèle d'ancre) se soigne en relançant `federation pair` avec la racine actuelle du pair.

## L'enregistrement DNS

Un domaine qui fédère annonce son point d'entrée sous son **propre** enregistrement SRV :

```text theme={null}
_jmap-federation._tcp.example.com.	IN SRV	0 1 443 mail.example.com.
```

L'hôte et le port sont ceux de `[federation] endpoint`. L'enregistrement sert à une seule chose : router une question de temps occupé au sujet d'une **adresse**. Quand quelqu'un cherche un créneau avec `carol@partner.example`, le serveur lit l'enregistrement `_jmap-federation._tcp` de `partner.example` par le résolveur validant de la box. Il ne l'utilise que s'il est **sûr au sens DNSSEC** et que sa cible est l'hôte du point d'entrée enregistré pour exactement un appairage actif. Pas d'enregistrement, une zone non signée, aucun appairage correspondant : personne n'est interrogé. Les chemins du Drive ne lisent jamais le DNS : ils appellent le point d'entrée enregistré à l'appairage.

Ce n'est jamais l'enregistrement `_jmap._tcp` des clients. Un client JMAP standard suit les cibles de cet enregistrement avec les identifiants de l'utilisateur, et le brouillon de fédération peut y nommer le serveur d'un autre exploitant. Cet enregistrement ne peut pas non plus dire qu'un domaine fédère, puisque n'importe quel fournisseur JMAP le publie.

* `oximail setup dns` le publie (par l'API Cloudflare) ou affiche sa ligne de zone, **seulement une fois `[federation]` activée**. Une installation neuve ne fédère jamais : l'enregistrement apparaît quand vous relancez `setup dns` après avoir ouvert la porte.
* `oximail check-dns` et la ligne `dns` de `oximail doctor` le vérifient quand la porte est ouverte, et ne le valident **que s'il est signé DNSSEC** : un pair ne route sur rien d'autre. Un enregistrement non signé est nommé à part d'un résolveur qui n'a pas pu prouver sa réponse.

## Le temps occupé d'une organisation à l'autre

Chaque personne décide qui peut lire son temps occupé : un **grant** nomme une organisation appairée. Il est créé par la personne seule, en JMAP (un administrateur peut révoquer, jamais accorder), et expire au bout d'un an sauf si la personne choisit explicitement autre chose ([partage](../developer/jmap-sharing#dune-organisation-à-lautre-la-fédération)). `oximail federation grants list` montre chaque grant avec sa dernière utilisation ; `federation grants revoke --id … --yes` en coupe un. Révoquer retire le chemin de lecture pour la suite et ne défait rien de ce qui a déjà été divulgué.

**Quand un pair interroge ce serveur.** Un serveur appairé relaie `Principal/getAvailability` pour **50 adresses** au plus, sur une fenêtre de **62 jours** au plus ; une requête qui dépasse l'une ou l'autre limite est refusée, jamais tronquée. La réponse ne porte que du **temps occupé fusionné** : aucun événement, aucun titre, aucune enveloppe d'heures de travail. Une adresse inconnue, une personne qui n'a rien accordé et une personne libre tout le temps donnent la **même** réponse : la porte ne sert pas d'oracle d'annuaire. Une adresse hors des domaines de courrier de l'organisation reçoit une réponse incomplète, avec la raison `notServed`, jamais « libre » : une route erronée apparaît donc comme incertaine. Une **divulgation** par personne est enregistrée, en une transaction, avant que la réponse parte : la personne la lit dans son journal des divulgations.

**Quand ce serveur interroge un pair.** `Event/proposeTimes` confie au demandeur fédéré les adresses de participants qu'aucun compte local ne détient. Celui-ci route chacune par l'[enregistrement DNS](#lenregistrement-dns), interroge les pairs en parallèle (cinquante adresses par appel) et attend **quatre secondes** en tout, routage compris. Une réponse n'est utilisée qu'une fois sa signature vérifiée. Un pair qui n'a pas donné de réponse vérifiée à temps place ses participants dans `unreachableEmails`, **jamais libres** ; une réponse distante incomplète les place dans `incompleteFor` ([agenda](../developer/jmap-calendar)).

Porte fermée, un grant n'autorise rien et personne n'est interrogé.

## Partager des dossiers du Drive

### Côté propriétaire : un partage par nœud

L'exploitant partage un dossier ou un fichier du Drive, en **lecture**, avec une organisation appairée. Il n'existe pour cela aucune surface JMAP ni web : la CLI est le seul rédacteur.

```bash theme={null}
oximail federation shares add --owner-email anna@example.com --path "Partages/Plans" --realm partner.example
oximail federation shares add --owner-email anna@example.com --path "Partages/Plans" --realm partner.example --apply
oximail federation shares list
oximail federation shares remove --id <id-du-partage> --apply
```

Le nœud se désigne par `--path` (depuis la racine du Drive du propriétaire) ou par `--node <id>`, le propriétaire par `--owner-email` ou `--owner-account-id`. La simulation résout le nœud, vérifie chaque règle et dit ce que l'exploitant de l'autre organisation pourra lire. `--expires-at <RFC 3339>` fixe une échéance facultative. Il n'y en a aucune par défaut, faute de durée décidée : un partage dure jusqu'à ce qu'on le retire. `--json` donne une réponse lisible par une machine.

Un partage est refusé, nommément, dans ces cas :

| Refus | Pourquoi |
| - | - |
| `not-paired`, `peering-not-active` | le realm n'est pas un appairage actif de cette organisation |
| `node-not-found`, `node-trashed` | le nœud est absent, dans la corbeille, ou sous un dossier dans la corbeille |
| `drive-root` | la racine d'un Drive ne se partage pas : partagez les dossiers eux-mêmes, pour qu'un partage n'ouvre jamais tout un Drive |
| `already-shared` | ce nœud est déjà partagé avec ce realm |
| `rights-not-supported` | seul `read` est servi |
| `invalid-expiry`, `expiry-in-past` | l'échéance ne se lit pas en RFC 3339, ou elle est passée |

Un partage **sert** tant que son appairage est actif et que son échéance n'est pas passée (`shares list` affiche `active`, `expired` ou `peering-inactive`). Chaque acte est consigné dans la chaîne d'audit de l'organisation (`federation.share.created`, `federation.share.removed`). Un partage est **retiré**, consigné et signalé aussitôt au serveur lecteur, quelle que soit la cause : `shares remove`, le nœud supprimé définitivement, le balayage de la corbeille, l'effacement du propriétaire. Il ne disparaît jamais en silence avec une ligne supprimée. Ce que l'autre organisation a déjà lu n'est pas défait.

Par la porte, le pair lit avec `FileNode/get`, `FileNode/query` et `FileNode/changes`, bornés au sous-arbre partagé : un parent, un frère, un nœud non partagé ou dans la corbeille répondent exactement comme un nœud inconnu. Le contenu est servi sur une seconde route, `/jmap/federation/content`, par blocs signés de **1 Mio**. Chaque bloc est demandé par nœud, contenu attendu et plage, jamais par un identifiant de blob nu : les blobs sont dédoublonnés, et un identifiant nu répondrait à la question « ce fichier existe-t-il quelque part sur ce serveur ». La divulgation du propriétaire est enregistrée au plus une fois par heure, par propriétaire et par organisation.

Chaque appairage a un **budget par classe**, pour qu'une copie de dossier n'affame jamais les lectures de temps occupé : disponibilité 20 requêtes par seconde (rafale de 40), fichiers 20 (rafale de 100), contenu 50 blocs par seconde (rafale de 100), et au plus huit lectures de contenu en cours par appairage. Un budget épuisé répond `limit`.

### Côté lecteur : le compte miroir

Ce qu'une organisation appairée partage avec vous apparaît dans un **compte miroir** : un compte partagé de votre organisation dont le Drive montre les dossiers que ce realm partage avec ce serveur.

```bash theme={null}
oximail federation mirror add --email partner-files@example.com --realm partner.example
oximail federation mirror add --email partner-files@example.com --realm partner.example --apply
oximail account grant …        # qui, parmi vos personnes, peut l'ouvrir, comme pour tout compte partagé
oximail federation mirror list
oximail federation mirror remove --email partner-files@example.com --apply
```

`mirror add --apply` crée un compte partagé, sans connexion possible, avec une racine de Drive (nom affiché « Shared by » suivi du realm, ou `--display-name`), et le déclare miroir : la capability `federation {realm}` sur son principal. La commande est refusée, nommément, quand le realm n'est pas un appairage **actif** avec un point d'entrée enregistré (`not-paired`, `peering-not-active`), ou quand il a déjà son miroir (`already-mirrored`). L'accès s'accorde sur le compte, jamais nœud par nœud. `mirror remove` retire la capability, et le serveur purge la copie à son passage suivant ; le compte reste.

Le miroir suit quatre règles :

* **Rien du propriétaire sur ce disque.** Le serveur copie l'arborescence partagée par la porte du pair, **en mémoire seulement** : aucune ligne de Drive, aucun blob, rien dans les sauvegardes, rien qu'une révocation pourrait manquer. Le prix, dit tel quel : à chaque redémarrage, l'arborescence est recopiée, et les clients du miroir reçoivent `cannotCalculateChanges` puis se resynchronisent.
* **Au plus `mirror_staleness_secs` de retard.** Le serveur demande les changements au propriétaire à chaque moitié de cette borne (120 s par défaut), et aussitôt quand le propriétaire envoie un avis. Un sous-arbre révoqué part aussitôt, et un appairage qui n'est plus actif purge la copie.
* **Lecture seule pour tout le monde.** Toute écriture sur un compte miroir, par n'importe quel client et n'importe quel rôle, est refusée avec `mirror-read-only`.
* **Jamais un dossier vide.** Tant que la copie n'est pas prête, la liste montre à la place un fichier d'état nommé : `(copy in progress from partner.example)`, `(partner.example unreachable since …)`, `(access revoked by partner.example)` ou `(no active pairing with partner.example)`. Un propriétaire injoignable laisse en place l'arborescence déjà chargée.

`mirror list` fonctionne serveur arrêté et montre l'état de l'appairage de chaque miroir. L'état de la copie elle-même vit dans le serveur en cours (la métrique `oximail_federation_mirrors{state}` : `copying`, `ready`, `unreachable`, `revoked`, `unpaired`).

### Ouvrir un fichier miroir

Un fichier miroir se télécharge comme les autres, par les portes de téléchargement web et JMAP, mais son contenu est **lu chez le propriétaire**, par nœud, un bloc signé de 1 Mio à la fois par la route de contenu du propriétaire (au plus huit blocs en cours par appairage, dix secondes par bloc), jamais dans le magasin de blobs de ce serveur. Un cache en mémoire, indexé par la version du contenu, absorbe les réouvertures d'un même geste (une suite bureautique ouvre plusieurs fois le même fichier) : une durée de `content_cache_secs`, `content_cache_mib` en tout, des fichiers jusqu'à `content_cache_file_mib`. Un fichier plus gros est lu chez le propriétaire à chaque fois ([configuration](#configuration)). Le cache n'est **jamais écrit sur le disque**, et il oublie les blocs d'un nœud avec le nœud. Un propriétaire injoignable est refusé nommément (`ownerUnreachable`, `503`), que le contenu soit en cache ou non : il n'existe pas de copie hors connexion. Un fichier miroir n'a pas de vignette.

<Warning>
  Une page de mémoire peut tout de même atteindre le swap ou un core dump, tous deux sur le volume que `doctor` mesure ([chiffrement au repos](./encryption-at-rest)). Un exploitant qui veut exclure même cela désactive le swap et les core dumps pour le service.
</Warning>

## Configuration

```toml theme={null}
[federation]
enabled = true                                        # obligatoire dans une section écrite ; section absente = désactivée
endpoint = "https://mail.example.com/jmap/federation" # ce que les pairs enregistrent ; le chemin doit être /jmap/federation
tls_pins = []                                         # facultatif : sha256/<base64 de l'empreinte SPKI>, la clé en service et la suivante
mirror_staleness_secs = 120                           # la copie d'un miroir a au plus cet âge
content_cache_secs = 60                               # durée de vie d'un bloc en cache d'un fichier miroir
content_cache_mib = 256                               # le plafond du cache, tous miroirs confondus (LRU)
content_cache_file_mib = 64                           # un fichier plus gros n'est jamais mis en cache
```

| Clé | Défaut | Règle |
| - | - | - |
| `enabled` | aucun | **Obligatoire** dans une section `[federation]` écrite : une section sans elle est refusée, jamais lue comme désactivée. Sans la section, la fédération est désactivée. |
| `endpoint` | aucun | `https://`, un nom DNS en minuscules (jamais une adresse littérale : TLS vérifie le nom), un port facultatif, le chemin `/jmap/federation` ; ni requête, ni fragment, ni identifiants. Exigé par `enabled = true`. |
| `tls_pins` | `[]` | Chacune `sha256/` suivi du base64 d'une empreinte SPKI de 32 octets, quatre au plus, stockées triées. Vide : les pairs valident votre certificat et n'épinglent rien. |
| `mirror_staleness_secs` | `120` | La borne d'âge d'un miroir ; une valeur inférieure à 10 vaut 10. |
| `content_cache_secs` | `60` | `120` au plus, et jamais au-dessus de `mirror_staleness_secs` : un bloc en cache ne doit pas survivre à l'arborescence qui le nomme. |
| `content_cache_mib` | `256` | La mémoire que le cache peut occuper ; les blocs les moins récemment utilisés partent les premiers. |
| `content_cache_file_mib` | `64` | Jamais au-dessus de `content_cache_mib`, sinon aucun fichier ne pourrait être mis en cache. |

`endpoint` et `tls_pins` sont ce que ce serveur annonce à ses pairs pendant la cérémonie : les changer change votre empreinte de transport, et chaque pair doit enregistrer la nouvelle. Les bornes sont vérifiées au démarrage du serveur porte ouverte (code de sortie `2` sur une valeur hors bornes) et par la ligne `federation_content_cache` de `doctor` ; `check-config` ne les vérifie pas.

## Garder l'identité en bon état

| Situation | Verbe |
| - | - |
| Le certificat de la clé de travail approche de sa fin (`doctor` avertit 30 jours avant et échoue une fois la date passée), ou une clé encore certifiée sous la forme antérieure à RFC 9421, qui n'est jamais envoyée à un pair | `oximail federation working-key rotate --tenant <id> --yes` : demande **une** clé papier de racine sur l'entrée standard (jamais en argument, qui finit dans `ps` et l'historique du shell) ; aucun pair n'a rien à faire. |
| Une clé papier est compromise (une enveloppe ouverte, un associé qui part) | `oximail federation roots retire --root <id> --yes` : cette sœur ne garantit plus rien dès cet instant, et son séquestre est effacé, si bien que sa clé papier n'ouvre plus rien. Refusé en dessous de deux racines vivantes, et pour la racine qui a signé la clé de travail actuelle (faites d'abord tourner la clé sur une autre sœur). |
| Un jeu de deux sœurs doit en perdre une, ou un lieu de garde a changé de mains | `oximail federation roots enrol --custody <étiquette> --yes` d'abord : affiche la nouvelle clé papier une seule fois. Une clé de travail signée par la nouvelle sœur est refusée par chaque pair tant que ce pair ne l'a pas épinglée (`federation pair --key …` de son côté). |
| La chaîne ne se vérifie plus (un signataire retiré à la main, une ligne modifiée, une ligne de clé de travail perdue) | `oximail federation working-key repair --tenant <id> --realm <domaine> --yes` : certifie une nouvelle clé de travail avec la clé papier d'une sœur inscrite, sous le realm qu'attestent les enregistrements et à une époque au-dessus de toutes celles enregistrées (`--epoch` la relève, jamais ne l'abaisse). Une identité saine est refusée : c'est le rôle de `rotate`. |
| Plus aucune sœur ne peut signer, ou l'identité est abandonnée | `oximail federation roots delete --tenant-id <id> --realm <domaine> --yes` : supprime chaque racine, vivante ou retirée, et la clé de travail, en une transaction avec sa ligne d'audit `federation.identity.deleted` ; le realm se saisit en confirmation. Ensuite `federation identity --realm …` crée une nouvelle identité, et **chaque** pair doit l'épingler de nouveau. |

## Lignes doctor et métriques

| Ligne `doctor` | Dit |
| - | - |
| `federation_identity` | ignorée sur une box qui ne détient aucune identité de fédération |
| `federation_identity_root` | échoue quand une racine n'a pas de séquestre (aucune clé papier ne peut la reconstruire) ; avertit quand une identité détient moins de deux sœurs |
| `federation_working_key` | échoue quand la chaîne d'une identité ne se vérifie pas (et nomme `working-key repair`), quand un certificat a expiré ou n'a pas de fenêtre de validité ; avertit dans les 30 jours qui précèdent la fin |
| `federation_certificate_format` | avertit, avec un compte, sur les clés de travail encore certifiées sous la forme antérieure à RFC 9421 |
| `federation_epoch_witness` | échoue quand un pair a montré à cette box l'un de ses propres certificats à une époque égale ou supérieure à celle qu'elle détient : la base est revenue en arrière. Vérifiez l'horloge, puis faites tourner la clé. (Le protocole ne renvoie pas encore un tel certificat ; l'époque tirée de l'horloge est la protection actuelle.) |
| `federation_peers` | compte les appairages et ceux qui dorment ; avertit quand un appairage attend une reconfirmation après une restauration ou parce qu'il précède le modèle d'ancre |
| `federation_jurisdiction` | avertit quand un pair s'est vu dire un autre pays que celui déclaré aujourd'hui, ou quand rien n'a été enregistré ; le remède est de relancer `federation pair` après avoir prévenu l'autre administrateur |
| `federation_node_shares` | compte les partages du Drive (actifs, expirés) ; avertit quand certains visent un appairage inactif, puisqu'ils ne servent rien |
| `federation_content_cache` | ce que le cache de contenu des miroirs a le droit de détenir ; échoue sur un réglage hors bornes ; ignorée porte fermée |
| `dns` | inclut `SRV _jmap-federation` quand la porte est ouverte : présent, visant le point d'entrée, signé DNSSEC |

Les métriques ne portent aucune étiquette de pair : `oximail_federation_door_requests_total{class,outcome}` (ce que la porte a répondu), `oximail_federation_door_content_octets_total` (le contenu partagé servi), `oximail_federation_mirrors{state}`, `oximail_federation_content_reads_total{source}` et `oximail_federation_content_octets_total{source}` (`remote` ou `cache`), `oximail_federation_content_cache_octets` et `oximail_federation_content_cache_blocks`, et `oximail_federation_grants_expiring{tenant}` ([exploitation](./operations#les-métriques)).

## Ce qui n'est pas servi

<Warning>
  La fédération sert les deux chemins de lecture ci-dessus, et rien d'autre. En particulier :

  * **Pas de courrier entre serveurs.** Le dépôt, le rôle de spool et le dépôt scellé sont spécifiés dans les brouillons ; la capability de transport les annonce absents.
  * **Pas d'appairage dans la bande.** L'appairage passe uniquement par la cérémonie en CLI ; un serveur n'annonce aucune méthode d'appairage dans la bande, et un domaine qui publie un enregistrement de fédération n'est jamais contacté avant qu'un humain l'appaire.
  * **Pas d'identité au niveau de la personne.** Le bénéficiaire est une organisation ; les requêtes ne sont pas signées par personne.
  * **Pas d'écriture dans un dossier partagé.** Les comptes miroirs sont en lecture seule. Un seul éditeur à la fois, avec un bail pris chez le propriétaire, et des dossiers épinglés « toujours disponibles hors connexion » au site lecteur sont prévus, pas construits. Aucun contenu n'est servi tant que le propriétaire est injoignable.
  * **Pas de partage depuis un client.** Les partages de nœud ne s'écrivent qu'en CLI, et la racine d'un Drive ne se partage jamais.
  * **Pas de jauge de joignabilité par appairage**, et pas d'échec de `doctor` quand un appairage actif est injoignable : décidé, pas construit.
</Warning>

La surface JMAP des grants et des divulgations est décrite sur la [page du partage](../developer/jmap-sharing#dune-organisation-à-lautre-la-fédération), le compte miroir vu par un client sur la [page des fichiers](../developer/jmap-files#les-comptes-miroirs), et les verbes dans la [référence CLI](./cli#fédération).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.