Federated via graft
0

Configure Feed

Select the types of activity you want to include in your feed.

graft-presentation / presentation-fr.md
18 kB 575 lines
1--- 2marp: true 3paginate: true 4backgroundColor: "#fff" 5theme: gaia 6lang: fr-FR 7style: | 8 section { font-size: 25px; } 9 h1 { color: #1a5fb4; } 10 h2 { color: #1a5fb4; } 11 h3 { color: #555; font-size: 24px; margin-bottom: 0.2em; } 12 table { font-size: 21px; } 13 code { font-size: 18px; } 14 section.wide table { font-size: 18px; } 15 section.part { background-color: #1a5fb4 !important; } 16 section.part h1, section.part h2, section.part p { color: #fff !important; } 17--- 18 19<!-- _class: lead --> 20 21# Forges & web décentralisé 22 23État des lieux au 10 septembre 2026 24 25--- 26 27<!-- _class: lead part --> 28<!-- _backgroundColor: #1a5fb4 --> 29<!-- _color: #ffffff --> 30 31# 1. Cadrage 32 33## code et collaboration 34 35--- 36 37## Automatisation de la mise en miroir 38 39**Le transport** du code est résolu depuis 2005 : git est distribué par construction, un dépôt peut exister à plusieurs endroits. 40 41**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. 42 43--- 44 45## Éléments non couverts par git 46 47Le véritable obstacle, c'est tout ce qui entoure un dépôt : tickets, 48propositions de modification, relectures, identité, droits. 49 50Ces éléments sont stockés dans la base de données d'un serveur Forgejo, en dehors de git. 51 52[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. 53 54--- 55 56<!-- _class: lead part --> 57<!-- _backgroundColor: #1a5fb4 --> 58<!-- _color: #ffffff --> 59 60# 2. État de la fédération dans Forgejo 61 62## Fonctionnalités livrées et fonctionnalités manquantes 63 64--- 65 66![bg right:33% fit](img/forgejo_v16.jpg) 67 68## Périmètre fonctionnel de la fédération [Forgejo](https://forgejo.org) 69 70### Fonctionne 71 72- Le favori fédéré : un fork mis en favori transmet ce favori au dépôt 73 d'origine. 74- Le suivi de comptes distants, avec un flux de leur activité. 75- Les fondations techniques : pages d'acteur, découverte, requêtes signées. 76 77### Pas implémenté 78 79Tickets, commentaires et propositions de modification fédérés. Modération et 80contrôle d'accès entre serveurs. 81 82--- 83 84## Fonctionnement du favori fédéré 85 86``` 87@alice@forgeA --(c'est quoi, ce dépôt ?)--> acteur du dépôt sur forgeB 88 --(« aimé », signé)---------> boîte de réception sur forgeB 89forgeB vérifie la signature --> compteur de favoris +1, favori ajouté au profil d'alice 90``` 91 92Le message part à sens unique, il est signé, il ne contient aucun texte : 93rien à modérer. 94 95C'est le test le plus simple pour vérifier que l'échange entre deux serveurs 96fonctionne. 97 98--- 99 100## Suivi de comptes entre Forgejo et la fédiverse 101 102Un compte Forgejo peut suivre un compte [Mastodon](https://joinmastodon.org) ou [GoToSocial](https://gotosocial.org), et l'inverse. 103Les commits et les versions apparaissent alors dans un fil social. 104 105C'est la première fonction de fédération visible pour quelqu'un qui ne 106développe pas. 107 108Seuls Forgejo, [Mastodon](https://joinmastodon.org) et [GoToSocial](https://gotosocial.org) sont acceptés pour l'instant. 109 110--- 111 112## Risque associé à l'activation de la fédération 113 114Le projet se réserve le droit de casser la fédération sans préavis. 115 116Les 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 117inutilisable pour tout usage ActivityPub. 118 119--- 120 121![bg right:38% fit](img/term404.jpg) 122 123## Adoption en production 124 125La fédération est désactivée par défaut, et les grandes instances publiques ne 126l'activent pas. 127 128Les points d'entrée de la fédération répondent 404 sur 129[codeberg.org](https://codeberg.org), [disroot](https://disroot.org) et 130[verdigado](https://verdigado.com). 131 132--- 133 134<!-- _class: lead part --> 135<!-- _backgroundColor: #1a5fb4 --> 136<!-- _color: #ffffff --> 137 138# 3. Autres solutions 139 140## Des solutions indépendantes d'ActivityPub 141 142--- 143 144## Mise en relation de deux forges par miroir 145 146Forgejo push ou pull déjà un dépôt vers une autre instance. Le code passe, 147les tickets non. 148 149Deux projets comblent une partie du manque : 150 151- **[forgesync](https://github.com/lukaswrz/forgesync)** copie tous les dépôts d'une Forgejo vers une autre, tickets et propositions compris. 152- **[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. 153- 154--- 155 156## [F3](https://code.forgejo.org/f3/f3-documentation) : migrer un projet, pas le fédérer 157 158F3 est un format d'export qui contient tout un projet : dépôt, tickets, 159propositions, commentaires, comptes. 160 161Le code de migration de Forgejo s'en sert déjà. 162 163--- 164 165![bg right:33% fit](img/authint.jpg) 166 167## [Authorized Integrations](https://forgejo.org/docs/latest/user/api/authorized-integrations/) : authentification entre serveurs 168 169Forgejo v16, juillet 2026 : **Authorized Integrations**. La CI d'une instance 170peut désormais s'authentifier sur les dépôts d'une autre, sans secret partagé 171ni jeton à renouveler. 172 173Un lien automatisable, arrivé cette année, sans ActivityPub. Nous l'avons 174testée en conditions réelles entre deux instances, f1 et f2.cyberwild.org. 175 176--- 177 178## Mise en place : exécuteur et confiance 179 180Un runner Forgejo (`forgejo-runner`), en mode host et sans Docker, est 181enregistré sur f1. Côté f2, une intégration autorisée fait confiance aux JWT 182émis par l'émetteur de f1, filtrés par une revendication. 183 184``` 185forgejo admin user create-authorized-integration \ 186 --username forgeadmin \ 187 --issuer https://f1.cyberwild.org/api/actions \ 188 --claim-eq repository=forgeadmin/testrepo \ 189 --scope write:repository \ 190 --repo forgeadmin/testrepo 191``` 192 193--- 194 195## Le CI de f1 demande un jeton OIDC à sa propre instance 196 197``` 198jobs: 199 inspect: 200 runs-on: linux-host 201 enable-openid-connect: true 202 steps: 203 - run: | 204 AUD="u:1:11412bf9-...-f06c" 205 curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ 206 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$AUD" 207``` 208 209Revendications du JWT reçu : `iss`, `repository`, `ref`, `workflow`, `sub`. Le 210jeton est signé par f1 et vérifiable par f2 sans contact préalable. 211 212--- 213 214## Le jeton sert directement à s'authentifier sur f2 215 216``` 217curl -X POST \ 218 -H "Authorization: Bearer $JWT" \ 219 -H "Content-Type: application/json" \ 220 --data '{"title":"Proposition de test depuis le CI de f1","head":"f1-ci-run-6","base":"main"}' \ 221 https://f2.cyberwild.org/api/v1/repos/forgeadmin/testrepo/pulls 222``` 223 224Aucun jeton n'est stocké côté f2 pour f1 : la confiance repose sur la 225signature du JWT et les règles de revendications, pas sur un secret échangé à 226l'avance. 227 228--- 229 230## Résultat : trois actions inter-instances réussies 231 232| Action déclenchée depuis f1 | Résultat sur f2 | 233|---|---| 234| Créer un fichier | HTTP 201 | 235| Créer une branche | HTTP 201 | 236| Ouvrir une proposition de modification | HTTP 201 | 237 238 239--- 240 241<!-- _class: lead part --> 242<!-- _backgroundColor: #1a5fb4 --> 243<!-- _color: #ffffff --> 244 245# 4. Comparaison avec d"autres systèmes décentralisés 246 247## Panorama des systèmes comparés 248 249--- 250 251![bg right:33% fit](img/forgefed.jpg) 252 253## [ForgeFed](https://forgefed.org) : une spécification distincte de Forgejo 254 255**ForgeFed** est une extension d'ActivityPub pensée pour les forges : dépôts, 256tickets, propositions, versions. 257 258**[Vervis](https://hackage.haskell.org/package/vervis)** en est l'implémentation de référence : une forge complète et 259séparée, pas un module à brancher sur Forgejo. 260 261Forgejo construit sa propre fédération. Le blog ForgeFed n'a rien publié depuis janvier 2025. 262 263--- 264 265<!-- _class: wide --> 266 267## Comparaison des modèles techniques 268 269| | [ActivityPub](https://www.w3.org/TR/activitypub/) | [ATProto](https://atproto.com) | [IPFS](https://ipfs.tech) | [Radicle](https://radicle.dev) | 270|---|---|---|---|---| 271| Organisé autour de | le serveur | l'utilisateur | le contenu | le dépôt | 272| Identité | une adresse sur un serveur | un identifiant portable | une clé | une clé, sans compte | 273| Données stockées | sur le serveur | pointées par l'identifiant | partout où copiées | sur les nœuds relais | 274| Droits | signatures, plus l'admin | des clés, on peut déménager | aucun | une liste de clés signée | 275| 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 | 276 277Radicle range tickets et propositions **dans le dépôt git lui-même** . 278 279--- 280 281<!-- _class: wide --> 282 283![bg right:26% fit](img/shipyard.jpg) 284 285## Comparaison des modèles de gouvernance 286 287| | Code | Gouvernance | 288|---|---|---| 289| ActivityPub | Mastodon, PeerTube, GoToSocial : AGPL | spécification W3C figée en 2018. Threads est propriétaire et fédère quand même | 290| ATProto | référence ouverte, auto-hébergeable | une société écrit le protocole, tient l'infrastructure | 291| 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 | 292| 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) | 293 294Ni ActivityPub ni Radicle ne dépendent d'une société.. 295 296--- 297 298![bg right:33% fit](img/bridgy.jpg) 299 300## Ponts entre réseaux sociaux décentralisés 301 302**[Bridgy Fed](https://fed.brid.gy)** relie la fédiverse, Bluesky et le web 303ouvert dans les deux sens. **[granary](https://github.com/snarfed/granary)**, en dessous traduit entre les formats. 304 305Ce sont des projets personnels. 306 307--- 308 309## Tentatives d'hébergement de git sur IPFS 310 311| Projet | État | 312|---|---| 313| [Gitlawb/node](https://github.com/Gitlawb/node), [ipgit](https://github.com/meyer1994/ipgit) | actifs en 2026, une centaine de favoris chacun | 314| git-remote-ipfs, pando, brig | génération précédente, abandonnée | 315 316Rien n'est utilisable en production. 317 318ATProto s'inspire du même principe : chaque contenu est identifié par une 319empreinte plutôt que par une adresse, comme sur IPFS. Mais contrairement à 320IPFS, ATProto associe ce contenu à des comptes utilisateurs identifiables. 321 322--- 323 324![bg right:33% fit](img/keyoxide.jpg) 325 326## Portabilité de l'identité 327 328**[Keyoxide](https://keyoxide.org)** produit des preuves d'identité 329décentralisées, déjà utilisées par Forgejo pour ses propres contacts. 330**[did:web](https://w3c-ccg.github.io/did-method-web/)** permet à un domaine de publier une identité portable dès aujourd'hui. 331 332Mais quitter une instance reste synonyme d'abandonner son identité, ses 333contributions et ses relations. Radicle évite ce défaut en fondant l'identité 334sur des clés plutôt que sur un compte. 335 336--- 337 338<!-- _class: lead part --> 339<!-- _backgroundColor: #1a5fb4 --> 340<!-- _color: #ffffff --> 341 342# 5. Démonstration pratique 343 344## Radicle testé entre r1 et r2.cyberwild.org 345 346--- 347 348## Mise en place : identités et connexion directe entre pairs 349 350Radicle 1.10.3 est installé sur les deux nœuds. Pas de serveur central : 351chaque nœud a sa propre identité (clé Ed25519) et écoute en pair-à-pair. 352Comme r1 et r2 sont sur le même réseau local, la connexion est directe, sans 353tunnel. 354 355``` 356rad auth --alias radicle1 357radicle-node --listen 0.0.0.0:8776 358 359# depuis r1, connexion directe au nœud r2 360rad node connect z6Mkfqb...2nbFDJg@192.168.1.108:8776 361``` 362 363--- 364 365## Un dépôt partagé, sans serveur 366 367``` 368# sur r1 : publier un dépôt existant sur le réseau 369rad init --name testrepo --default-branch master --public 370# -> rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8 371 372# sur r2 : récupérer le même dépôt directement depuis r1 373rad clone rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8 374``` 375 376Le dépôt, avec ses fichiers, est répliqué intégralement entre les deux nœuds 377via le protocole pair-à-pair, sans jamais passer par un serveur HTTP. 378 379--- 380 381## Un patch (l'équivalent Radicle d'une proposition de modification) 382 383``` 384# sur r2 : proposer un changement 385git checkout -b feature-dummy4 386git commit -am "add dummy4.txt" 387git push rad HEAD:refs/patches 388# -> Patch 922387e... ouvert 389 390# sur r1 (mainteneur) : relire et fusionner 391rad patch checkout 922387e 392git merge --no-ff feature-dummy4-review 393git push rad master 394``` 395 396--- 397 398## Résultat : fédération pair-à-pair, sans passerelle HTTP obligatoire 399 400| Étape | Résultat | 401|---|---| 402| Connexion directe r1 et r2 | établie | 403| Réplication du dépôt sur r2 | fichiers identiques | 404| Patch ouvert sur r2, visible sur r1 | propagé automatiquement | 405| Fusion du patch sur r1 | master mis à jour | 406 407Contrairement à 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. 408 409--- 410 411<!-- _class: lead part --> 412<!-- _backgroundColor: #1a5fb4 --> 413<!-- _color: #ffffff --> 414 415# 6. Faire dialoguer Forgejo et Radicle 416 417## graft : un miroir entre les deux mondes déjà testés 418 419--- 420 421## Ce que fait [graft](https://github.com/jeanbaptiste/graft) 422 423Un 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. 424 425Il tourne à intervalle régulier, garde son état dans une base SQLite locale, et 426ne force jamais un push. Les vraies divergences sont signalées et laissées à 427l'arbitrage humain plutôt que résolues automatiquement. 428 429Projet récent (GPLv3, quatre commits, aucune version publiée) : une 430démonstration de faisabilité, pas un outil éprouvé. 431 432--- 433 434## Relier f1 et r1 435 436```yaml 437sync_interval: 5m 438state_db: /var/lib/graft/state.db 439 440repos: 441 - name: testrepo 442 forgejo: 443 base_url: https://f1.cyberwild.org 444 owner: forgeadmin 445 repo: testrepo 446 token_file: /etc/graft/testrepo.token 447 radicle: 448 rid: rad:z2YWuPL53okTkr5mgb7WCKsfxG7h8 449 http_base_url: https://r1.cyberwild.org 450 rad_home: /home/graft/.radicle 451 sync: 452 git: true 453 issues: true 454 patches: true 455``` 456 457Le même dépôt que dans la démonstration Radicle, maintenant relié à f1 plutôt 458qu'à r2 seul. 459 460--- 461 462## Ce qui se synchronise et limites actuelles 463 464- **Code** : la branche par défaut, uniquement en avance rapide. 465- **Tickets** : un ticket Forgejo devient un ticket Radicle et inversement, 466 mais seulement à la création. 467- **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. 468 469Aucun force-push. 470--- 471 472## Complémentarité 473 474graft ne tranche pas entre Radicle et Forgejo, il les traite comme 475complémentaires : le même projet existe sur les deux à la fois. 476 477Ce que ça ne résout pas : l'identité reste double, un compte Forgejo d'un 478côté, une clé Radicle de l'autre. 479 480--- 481 482<!-- _class: lead part --> 483<!-- _backgroundColor: #1a5fb4 --> 484<!-- _color: #ffffff --> 485 486# 7. Fonctions sociales de graft 487 488## Un tableau de bord, et des ponts vers Discourse, Zulip, Tangled 489 490--- 491 492![bg right:40% fit](img/graft_dashboard.png) 493 494## Le tableau de bord graft 495 496Une page HTML unique, régénérée à chaque cycle de synchronisation : la liste 497des dépôts, leur nombre de miroirs, et un flux d'activité récente (les 10 498derniers commits, tickets, patches et commentaires). 499 500Volontairement plat : pas de base de données à interroger, pas 501d'authentification, juste un fichier HTML servi par le démon lui-même. 502 503--- 504 505![bg right:38% fit](img/graft_social.png) 506 507## Une identité fédiverse par dépôt 508 509Chaque série synchronisée (`constitution`, `federation-x`, `graft-source`...) 510obtient sa propre identité ActivityPub : `@série@graft.cyberwild.org`, avec 511WebFinger, Actor et Outbox interrogeables. 512 513Une entrée AT Proto / Bluesky par série existe aussi dans le modèle, prête à 514être activée dès qu'une clé d'app y est associée — « not configured » pour 515l'instant. 516 517--- 518 519<!-- _class: lead part --> 520<!-- _backgroundColor: #1a5fb4 --> 521<!-- _color: #ffffff --> 522 523# Ponts vers Discourse, Zulip et Tangled 524 525## Faire vivre l'activité de graft ailleurs que sur une forge 526 527--- 528 529![bg right:35% fit](img/discourse_bridge.png) 530 531## Pont vers Discourse 532 533Un démon séparé (`graft-discourse`), branché sur le flux ActivityPub de 534graft : chaque série synchronisée devient une catégorie Discourse 535(« Federated Repos »), chaque ticket ou patch un sujet. 536 537Les réponses sur Discourse repartent en commentaire vers le ticket 538Forgejo/Radicle d'origine, marquées « via Fediverse ». Le pont ignore ses 539propres messages pour ne pas boucler. 540 541--- 542 543![bg right:35% fit](img/zulip_bridge.png) 544 545## Pont vers Zulip 546 547Même principe, décliné pour Zulip (`graft-zulip`) : un canal par série 548(ici `constitution`), un fil (*topic*) par ticket. Zulip distingue le canal 549et le sujet là où Discourse n'a qu'une catégorie et un sujet — les deux 550démons partagent l'essentiel de leur code, seule la couche protocole change. 551 552--- 553 554![bg right:35% fit](img/tangled_bridge.png) 555 556## Vers Tangled et AT Proto 557 558Tangled (une forge Git construite sur AT Proto/Bluesky) demande une identité 559signée par un PDS pour enregistrer un serveur Git (*knot*). Un PDS a été 560installé pour produire ce DID, `tangled.cyberwild.org` a été enregistré et 561vérifié : la prochaine étape naturelle est d'y raccrocher les mêmes séries 562que sur Forgejo et Radicle. 563 564--- 565 566![bg right:28% fit](img/radicle.jpg) 567 568## Synthèse et questions 569 570**Discussion :** 571 572- Qui modère une proposition de modification abusive venue d'un autre 573 serveur ? 574- Les miroirs et F3 marchent déjà. ActivityPub résout-il le vrai problème ? 575- Radicle et Forgejo : rivaux, ou deux moitiés de la même réponse ?