--- marp: true paginate: true backgroundColor: "#fff" theme: gaia lang: fr-FR style: | section { font-size: 25px; } h1 { color: #1a5fb4; } h2 { color: #1a5fb4; } h3 { color: #555; font-size: 24px; margin-bottom: 0.2em; } table { font-size: 21px; } code { font-size: 18px; } section.wide table { font-size: 18px; } section.part { background-color: #1a5fb4 !important; } section.part h1, section.part h2, section.part p { color: #fff !important; } --- # Forges & web décentralisé État des lieux au 10 septembre 2026 --- # 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](https://www.w3.org/TR/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 --- ![bg right:33% fit](img/forgejo_v16.jpg) ## Périmètre fonctionnel de la fédération [Forgejo](https://forgejo.org) ### 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](https://joinmastodon.org) ou [GoToSocial](https://gotosocial.org), 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](https://joinmastodon.org) et [GoToSocial](https://gotosocial.org) 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. --- ![bg right:38% fit](img/term404.jpg) ## 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](https://codeberg.org), [disroot](https://disroot.org) et [verdigado](https://verdigado.com). --- # 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](https://github.com/lukaswrz/forgesync)** copie tous les dépôts d'une Forgejo vers une autre, tickets et propositions compris. - **[gitea-mirror](https://github.com/RayLabsHQ/gitea-mirror)** fait la même chose avec une interface web, et transfère aussi étiquettes, jalons, versions et wikis. - --- ## [F3](https://code.forgejo.org/f3/f3-documentation) : 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à. --- ![bg right:33% fit](img/authint.jpg) ## [Authorized Integrations](https://forgejo.org/docs/latest/user/api/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 --- ![bg right:33% fit](img/forgefed.jpg) ## [ForgeFed](https://forgefed.org) : une spécification distincte de Forgejo **ForgeFed** est une extension d'ActivityPub pensée pour les forges : dépôts, tickets, propositions, versions. **[Vervis](https://hackage.haskell.org/package/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](https://www.w3.org/TR/activitypub/) | [ATProto](https://atproto.com) | [IPFS](https://ipfs.tech) | [Radicle](https://radicle.dev) | |---|---|---|---|---| | 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** . --- ![bg right:26% fit](img/shipyard.jpg) ## 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](https://github.com/ipfs/kubo) et [Helia](https://github.com/ipfs/helia), MIT | fondation, mais Protocol Labs possède les domaines et arrête son financement le 30 septembre 2026 | | Radicle | [Heartwood](https://github.com/radicle-dev/heartwood), MIT et Apache 2.0 | mené par ses mainteneurs, financé par le [DAO Radworks](https://radworks.org) | Ni ActivityPub ni Radicle ne dépendent d'une société.. --- ![bg right:33% fit](img/bridgy.jpg) ## Ponts entre réseaux sociaux décentralisés **[Bridgy Fed](https://fed.brid.gy)** relie la fédiverse, Bluesky et le web ouvert dans les deux sens. **[granary](https://github.com/snarfed/granary)**, en dessous traduit entre les formats. Ce sont des projets personnels. --- ## Tentatives d'hébergement de git sur IPFS | Projet | État | |---|---| | [Gitlawb/node](https://github.com/Gitlawb/node), [ipgit](https://github.com/meyer1994/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. --- ![bg right:33% fit](img/keyoxide.jpg) ## Portabilité de l'identité **[Keyoxide](https://keyoxide.org)** produit des preuves d'identité décentralisées, déjà utilisées par Forgejo pour ses propres contacts. **[did:web](https://w3c-ccg.github.io/did-method-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](https://github.com/jeanbaptiste/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 ```yaml 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. --- ![bg right:28% fit](img/radicle.jpg) ## 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 ?