Forges & web décentralisé

État des lieux au 10 septembre 2026 (test alice->f1)

1. Cadrage

code et collaboration

Automatisation de la mise en miroir

Le transport du code est résolu depuis 2005 : git est distribué par construction, un dépôt peut exister à plusieurs endroits.

L'orchestration n'existe pas. Chaque miroir se configure à la main, instance par instance. Chaque projet écrit elle-même l'intégration continue qui l'entretient.

Éléments non couverts par git

Le véritable obstacle, c'est tout ce qui entoure un dépôt : tickets,
propositions de modification, relectures, identité, droits.

Ces éléments sont stockés dans la base de données d'un serveur Forgejo, en dehors de git.

ActivityPub, le protocole de la fédiverse, les fait circuler : il transporte de petits messages (« créé », « aimé », « suivi »), pas des fichiers.

2. État de la fédération dans Forgejo

Fonctionnalités livrées et fonctionnalités manquantes

Périmètre fonctionnel de la fédération Forgejo

Fonctionne

  • Le favori fédéré : un fork mis en favori transmet ce favori au dépôt
    d'origine.
  • Le suivi de comptes distants, avec un flux de leur activité.
  • Les fondations techniques : pages d'acteur, découverte, requêtes signées.

Pas implémenté

Tickets, commentaires et propositions de modification fédérés. Modération et
contrôle d'accès entre serveurs.

Fonctionnement du favori fédéré

@alice@forgeA   --(c'est quoi, ce dépôt ?)-->   acteur du dépôt sur forgeB
                --(« aimé », signé)--------->   boîte de réception sur forgeB
forgeB vérifie la signature  -->  compteur de favoris +1, favori ajouté au profil d'alice

Le message part à sens unique, il est signé, il ne contient aucun texte :
rien à modérer.

C'est le test le plus simple pour vérifier que l'échange entre deux serveurs
fonctionne.

Suivi de comptes entre Forgejo et la fédiverse

Un compte Forgejo peut suivre un compte Mastodon ou GoToSocial, et l'inverse.
Les commits et les versions apparaissent alors dans un fil social.

C'est la première fonction de fédération visible pour quelqu'un qui ne
développe pas.

Seuls Forgejo, Mastodon et GoToSocial sont acceptés pour l'instant.

Risque associé à l'activation de la fédération

Le projet se réserve le droit de casser la fédération sans préavis.

Les autres serveurs mémorisent le domaine et les clés d'une instance dès que la fédération est active. Une rupture peut rendre ce domaine définitivement
inutilisable pour tout usage ActivityPub.

Adoption en production

La fédération est désactivée par défaut, et les grandes instances publiques ne
l'activent pas.

Les points d'entrée de la fédération répondent 404 sur
codeberg.org, disroot et
verdigado.

3. Autres solutions

Des solutions indépendantes d'ActivityPub

Mise en relation de deux forges par miroir

Forgejo push ou pull déjà un dépôt vers une autre instance. Le code passe,
les tickets non.

Deux projets comblent une partie du manque :

  • forgesync copie tous les dépôts d'une Forgejo vers une autre, tickets et propositions compris.
  • gitea-mirror fait la même chose avec une interface web, et transfère aussi étiquettes, jalons, versions et wikis.

F3 : migrer un projet, pas le fédérer

F3 est un format d'export qui contient tout un projet : dépôt, tickets,
propositions, commentaires, comptes.

Le code de migration de Forgejo s'en sert déjà.

Authorized Integrations : authentification entre serveurs

Forgejo v16, juillet 2026 : Authorized Integrations. La CI d'une instance
peut désormais s'authentifier sur les dépôts d'une autre, sans secret partagé
ni jeton à renouveler.

Un lien automatisable, arrivé cette année, sans ActivityPub. Nous l'avons
testée en conditions réelles entre deux instances, f1 et f2.cyberwild.org.

Mise en place : exécuteur et confiance

Un runner Forgejo (forgejo-runner), en mode host et sans Docker, est
enregistré sur f1. Côté f2, une intégration autorisée fait confiance aux JWT
émis par l'émetteur de f1, filtrés par une revendication.

forgejo admin user create-authorized-integration \
  --username forgeadmin \
  --issuer https://f1.cyberwild.org/api/actions \
  --claim-eq repository=forgeadmin/testrepo \
  --scope write:repository \
  --repo forgeadmin/testrepo

Le CI de f1 demande un jeton OIDC à sa propre instance

jobs:
  inspect:
    runs-on: linux-host
    enable-openid-connect: true
    steps:
      - run: |
          AUD="u:1:11412bf9-...-f06c"
          curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$AUD"

Revendications du JWT reçu : iss, repository, ref, workflow, sub. Le
jeton est signé par f1 et vérifiable par f2 sans contact préalable.

Le jeton sert directement à s'authentifier sur f2

curl -X POST \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data '{"title":"Proposition de test depuis le CI de f1","head":"f1-ci-run-6","base":"main"}' \
  https://f2.cyberwild.org/api/v1/repos/forgeadmin/testrepo/pulls

Aucun jeton n'est stocké côté f2 pour f1 : la confiance repose sur la
signature du JWT et les règles de revendications, pas sur un secret échangé à
l'avance.

Résultat : trois actions inter-instances réussies

Action déclenchée depuis f1 Résultat sur f2
Créer un fichier HTTP 201
Créer une branche HTTP 201
Ouvrir une proposition de modification HTTP 201

4. Comparaison avec d"autres systèmes décentralisés

Panorama des systèmes comparés

ForgeFed : une spécification distincte de Forgejo

ForgeFed est une extension d'ActivityPub pensée pour les forges : dépôts,
tickets, propositions, versions.

Vervis en est l'implémentation de référence : une forge complète et
séparée, pas un module à brancher sur Forgejo.

Forgejo construit sa propre fédération. Le blog ForgeFed n'a rien publié depuis janvier 2025.

Comparaison des modèles techniques

ActivityPub ATProto IPFS Radicle
Organisé autour de le serveur l'utilisateur le contenu le dépôt
Identité une adresse sur un serveur un identifiant portable une clé une clé, sans compte
Données stockées sur le serveur pointées par l'identifiant partout où copiées sur les nœuds relais
Droits signatures, plus l'admin des clés, on peut déménager aucun une liste de clés signée
Point faible changer de serveur = changer d'identité une société écrit les règles pas de contrôle d'accès sans relais, le projet disparaît

Radicle range tickets et propositions dans le dépôt git lui-même .

Comparaison des modèles de gouvernance

Code Gouvernance
ActivityPub Mastodon, PeerTube, GoToSocial : AGPL spécification W3C figée en 2018. Threads est propriétaire et fédère quand même
ATProto référence ouverte, auto-hébergeable une société écrit le protocole, tient l'infrastructure
IPFS Kubo et Helia, MIT fondation, mais Protocol Labs possède les domaines et arrête son financement le 30 septembre 2026
Radicle Heartwood, MIT et Apache 2.0 mené par ses mainteneurs, financé par le DAO Radworks

Ni ActivityPub ni Radicle ne dépendent d'une société..

Ponts entre réseaux sociaux décentralisés

Bridgy Fed relie la fédiverse, Bluesky et le web
ouvert dans les deux sens. granary, en dessous traduit entre les formats.

Ce sont des projets personnels.

Tentatives d'hébergement de git sur IPFS

Projet État
Gitlawb/node, ipgit actifs en 2026, une centaine de favoris chacun
git-remote-ipfs, pando, brig génération précédente, abandonnée

Rien n'est utilisable en production.

ATProto s'inspire du même principe : chaque contenu est identifié par une
empreinte plutôt que par une adresse, comme sur IPFS. Mais contrairement à
IPFS, ATProto associe ce contenu à des comptes utilisateurs identifiables.

Portabilité de l'identité

Keyoxide produit des preuves d'identité
décentralisées, déjà utilisées par Forgejo pour ses propres contacts.
did:web permet à un domaine de publier une identité portable dès aujourd'hui.

Mais quitter une instance reste synonyme d'abandonner son identité, ses
contributions et ses relations. Radicle évite ce défaut en fondant l'identité
sur des clés plutôt que sur un compte.

5. Démonstration pratique

Radicle testé entre r1 et r2.cyberwild.org

Mise en place : identités et connexion directe entre pairs

Radicle 1.10.3 est installé sur les deux nœuds. Pas de serveur central :
chaque nœud a sa propre identité (clé Ed25519) et écoute en pair-à-pair.
Comme r1 et r2 sont sur le même réseau local, la connexion est directe, sans
tunnel.

rad auth --alias radicle1
radicle-node --listen 0.0.0.0:8776

# depuis r1, connexion directe au nœud r2
rad node connect z6Mkfqb...2nbFDJg@192.168.1.108:8776

Un dépôt partagé, sans serveur

# sur r1 : publier un dépôt existant sur le réseau
rad init --name testrepo --default-branch master --public
# -> rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8

# sur r2 : récupérer le même dépôt directement depuis r1
rad clone rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8

Le dépôt, avec ses fichiers, est répliqué intégralement entre les deux nœuds
via le protocole pair-à-pair, sans jamais passer par un serveur HTTP.

Un patch (l'équivalent Radicle d'une proposition de modification)

# sur r2 : proposer un changement
git checkout -b feature-dummy4
git commit -am "add dummy4.txt"
git push rad HEAD:refs/patches
# -> Patch 922387e... ouvert

# sur r1 (mainteneur) : relire et fusionner
rad patch checkout 922387e
git merge --no-ff feature-dummy4-review
git push rad master

Résultat : fédération pair-à-pair, sans passerelle HTTP obligatoire

Étape Résultat
Connexion directe r1 et r2 établie
Réplication du dépôt sur r2 fichiers identiques
Patch ouvert sur r2, visible sur r1 propagé automatiquement
Fusion du patch sur r1 master mis à jour

Contrairement à Forgejo, aucune passerelle HTTP n'est nécessaire pour fédérer : l'identité et le partage reposent sur les clés des nœuds, pas sur un serveur public, cohérent avec le tableau de comparaison de la section précédente.

6. Faire dialoguer Forgejo et Radicle

graft : un miroir entre les deux mondes déjà testés

Ce que fait graft

Un démon qui synchronise, entre une instance Forgejo et un nœud Radicle : le code, les tickets, et les propositions de modification dans les deux sens.

Il tourne à intervalle régulier, garde son état dans une base SQLite locale, et
ne force jamais un push. Les vraies divergences sont signalées et laissées à
l'arbitrage humain plutôt que résolues automatiquement.

Projet récent (GPLv3, quatre commits, aucune version publiée) : une
démonstration de faisabilité, pas un outil éprouvé.

Relier f1 et r1

sync_interval: 5m
state_db: /var/lib/graft/state.db

repos:
  - name: testrepo
    forgejo:
      base_url: https://f1.cyberwild.org
      owner: forgeadmin
      repo: testrepo
      token_file: /etc/graft/testrepo.token
    radicle:
      rid: rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8
      http_base_url: https://r1.cyberwild.org
      rad_home: /home/graft/.radicle
    sync:
      git: true
      issues: true
      patches: true

Le même dépôt que dans la démonstration Radicle, maintenant relié à f1 plutôt
qu'à r2 seul.

Ce qui se synchronise et limites actuelles

  • Code : la branche par défaut, uniquement en avance rapide.
  • Tickets : un ticket Forgejo devient un ticket Radicle et inversement,
    mais seulement à la création.
  • Propositions de modification : une PR Forgejo ouvre un patch Radicle en poussant son commit de tête vers refs/patches, et inversement un patch Radicle ouvre une PR Forgejo.

Aucun force-push.

Complémentarité

graft ne tranche pas entre Radicle et Forgejo, il les traite comme
complémentaires : le même projet existe sur les deux à la fois.

Ce que ça ne résout pas : l'identité reste double, un compte Forgejo d'un
côté, une clé Radicle de l'autre.

7. Fonctions sociales de graft

Un tableau de bord, et des ponts vers Discourse, Zulip, Tangled

Le tableau de bord graft

Une page HTML unique, régénérée à chaque cycle de synchronisation : la liste
des dépôts, leur nombre de miroirs, et un flux d'activité récente (les 10
derniers commits, tickets, patches et commentaires).

Volontairement plat : pas de base de données à interroger, pas
d'authentification, juste un fichier HTML servi par le démon lui-même.

Une identité fédiverse par dépôt

Chaque série synchronisée (constitution, federation-x, graft-source...)
obtient sa propre identité ActivityPub : @série@graft.cyberwild.org, avec
WebFinger, Actor et Outbox interrogeables.

Une entrée AT Proto / Bluesky par série existe aussi dans le modèle, prête à
être activée dès qu'une clé d'app y est associée — « not configured » pour
l'instant.

Ponts vers Discourse, Zulip et Tangled

Faire vivre l'activité de graft ailleurs que sur une forge

Pont vers Discourse

Un démon séparé (graft-discourse), branché sur le flux ActivityPub de
graft : chaque série synchronisée devient une catégorie Discourse
(« Federated Repos »), chaque ticket ou patch un sujet.

Les réponses sur Discourse repartent en commentaire vers le ticket
Forgejo/Radicle d'origine, marquées « via Fediverse ». Le pont ignore ses
propres messages pour ne pas boucler.

Pont vers Zulip

Même principe, décliné pour Zulip (graft-zulip) : un canal par série
(ici constitution), un fil (topic) par ticket. Zulip distingue le canal
et le sujet là où Discourse n'a qu'une catégorie et un sujet — les deux
démons partagent l'essentiel de leur code, seule la couche protocole change.

Vers Tangled et AT Proto

Tangled (une forge Git construite sur AT Proto/Bluesky) demande une identité
signée par un PDS pour enregistrer un serveur Git (knot). Un PDS a été
installé pour produire ce DID, tangled.cyberwild.org a été enregistré et
vérifié : la prochaine étape naturelle est d'y raccrocher les mêmes séries
que sur Forgejo et Radicle.

Synthèse et questions

Discussion :

  • Qui modère une proposition de modification abusive venue d'un autre
    serveur ?
  • Les miroirs et F3 marchent déjà. ActivityPub résout-il le vrai problème ?
  • Radicle et Forgejo : rivaux, ou deux moitiés de la même réponse ?