Radicle Protocol Guide.html
1 <!DOCTYPE html> 2 <html lang="en-US"> 3 <head> 4 <title> 5 6 Radicle Protocol Guide 7 8 </title> 9 <link rel="shortcut icon" href="/assets/images/radicle.svg"/> 10 <link rel="canonical" href="https://radicle.xyz"/> 11 <meta http-equiv="content-type" content="text/html;charset=utf-8"> 12 <meta name="description" content="Radicle is a decentralized platform for code collaboration, offering secure and sovereign infrastructure for developers."> 13 <meta name="viewport" content="width=device-width, initial-scale=1"> 14 <meta name="twitter:card" content="summary"/> 15 <meta name="twitter:image" content="https://radicle.xyz/assets/images/og-card.png"/> 16 <meta name="twitter:site" content="@radicle"/> 17 <meta name="twitter:creator" content="@radicle"/> 18 <meta property="og:image" content="https://radicle.xyz/assets/images/og-card.png"/> 19 <meta property="og:url" content="https://radicle.xyz/guides/protocol/"/> 20 <meta property="og:type" content="website"/> 21 <meta property="og:title" content="Radicle"/> 22 <meta property="og:description" content="Sovereign code infrastructure."/> 23 <script defer data-domain="radicle.xyz" src="https://plausible.io/js/script.js"></script> 24 25 <link rel="stylesheet" type="text/css" href="/assets/css/guide.css"/> 26 </head> 27 <body> 28 <header> 29 <div class="title"> 30 <a href="/guides"> 31 <img src="/assets/images/radicle.svg" alt="" /> 32 <span>Guides</span> 33 </a> 34 </div> 35 <nav> 36 </nav> 37 <button class="toggle" id="toggle-theme"><!-- Set by script --></button> 38 </header> 39 <main> 40 <h1>Radicle Protocol Guide</h1> 41 <p class="subtitle">How Radicle works under the hood</p> 42 <img class="banner" src="/assets/images/banners/23.medium.png" /> 43 <ul class="toc"><li class="toc-h2"><a href="#introduction">Introduction</a></li><li class="toc-h2"><a href="#nodes">Nodes</a><ul><li class="toc-h3"><a href="#seeding-repositories">Seeding Repositories</a></li><li class="toc-h3"><a href="#node-identifiers-nids">Node Identifiers (NIDs)</a></li><li class="toc-h3"><a href="#running-a-node">Running a Node</a></li></ul></li><li class="toc-h2"><a href="#peer-to-peer-protocol">Peer-to-peer Protocol</a><ul><li class="toc-h3"><a href="#gossip-protocol">Gossip Protocol</a></li><li class="toc-h3"><a href="#transport-encryption--privacy">Transport Encryption & Privacy</a></li><li class="toc-h3"><a href="#replication-via-git">Replication via Git</a></li><li class="toc-h3"><a href="#bootstrap-nodes">Bootstrap Nodes</a></li><li class="toc-h3"><a href="#federation-vs-peer-to-peer">Federation vs. Peer-to-peer</a></li></ul></li><li class="toc-h2"><a href="#repositories">Repositories</a><ul><li class="toc-h3"><a href="#delegates">Delegates</a></li><li class="toc-h3"><a href="#identity-document">Identity Document</a></li><li class="toc-h3"><a href="#private-repositories">Private Repositories</a></li><li class="toc-h3"><a href="#repository-identifier-rid">Repository Identifier (RID)</a></li></ul></li><li class="toc-h2"><a href="#local-first-storage">Local-First Storage</a><ul><li class="toc-h3"><a href="#working-vs-stored-copy">Working vs. Stored Copy</a></li><li class="toc-h3"><a href="#storage-layout">Storage Layout</a></li><li class="toc-h3"><a href="#git-url-scheme">Git URL Scheme</a></li></ul></li><li class="toc-h2"><a href="#trust-through-self-certification">Trust through Self-Certification</a><ul><li class="toc-h3"><a href="#canonical-branches">Canonical Branches</a></li><li class="toc-h3"><a href="#self-certifying-repositories">Self-certifying Repositories</a><ul><li class="toc-h4"><a href="#signed-refs">Signed Refs</a></li></ul></li></ul></li><li class="toc-h2"><a href="#collaborative-objects">Collaborative Objects</a><ul><li class="toc-h3"><a href="#concurrency--consistency">Concurrency & Consistency</a></li><li class="toc-h3"><a href="#extending-cobs">Extending COBs</a></li></ul></li><li class="toc-h2"><a href="#conclusion">Conclusion</a></li></ul> 44 <hr /> 45 <p>Heartwood, the latest generation of the <a href="https://radicle.xyz/">Radicle</a> protocol establishes a 46 sovereign data network for code collaboration and publishing, built on top of 47 <a href="https://git-scm.com/">Git</a>. In Radicle, users maintain local copies of their repositories of 48 interest and related social artifacts such as issues and patches. Instead 49 of depending on a centralized service like GitHub, each participant in Radicle 50 operates a node that is capable of running on a personal computer, and is 51 connected via a peer-to-peer network.</p> 52 53 <p>Nodes, identified by <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public keys</a>, host and synchronize Git repositories 54 across the network, using a novel gossip protocol for peer and repository 55 discovery, alongside Git’s <a href="https://git-scm.com/docs/protocol-v2">protocol</a> for data replication. In 56 combination, this allows nodes to locate, replicate, and verify any repository 57 published to the network, provided at least one other peer seeding the 58 repository is online. Since Radicle is built on Git, it can easily interoperate 59 with existing tools and workflows.</p> 60 61 <p>Radicle’s architecture is <a href="https://www.inkandswitch.com/local-first/">local-first</a>, ensuring continuous access to one’s 62 repositories directly from their device, regardless of internet connectivity. 63 Repositories have unique identifiers and are self-certifying, meaning all 64 actions, from committing code to adding a comment to an issue, are performed 65 locally and <a href="https://en.wikipedia.org/wiki/Digital_signature">cryptographically signed</a>, allowing peers to verify 66 authenticity and data provenance once propagated to the network. This allows 67 trust to be established without reliance on a centralized authority.</p> 68 69 <p>Radicle is designed for extensibility, allowing for diverse use cases without 70 necessitating modifications at the protocol level. This guide delves into the 71 capabilities of Radicle’s initial release, which has a focus on code 72 collaboration and code publishing. Nonetheless, a range of other applications 73 is foreseen in the future and possible today, including knowledge sharing, 74 project coordination, and data set collaboration.</p> 75 76 <h2 id="introduction">Introduction</h2> 77 78 <p>Git, the most widely-used distributed version control system, enables users to 79 maintain and modify personal copies of data repositories, commonly for source 80 code control. Its structure for direct user-to-user collaboration, while 81 feasible, is often cumbersome since Git primarily focuses on version control 82 rather than collaboration. As a result, users frequently opt for centralized 83 <a href="https://en.wikipedia.org/wiki/Forge_(software)">forges</a> like GitHub or GitLab, which offer enhanced interfaces and 84 collaborative tools on top of Git, such as project management and code review. 85 This dependency, however, can result in vendor lock-in since it places a 86 project’s social artifacts (e.g. issues, comments, pull requests) out of user 87 control, potentially compromising data sovereignty and other user freedoms.</p> 88 89 <p>Traditional self-hosted forges like <a href="https://about.gitea.com/">Gitea</a> or <a href="https://forgejo.org/">Forgejo</a> provide more 90 sovereignty but often lead to fragmented collaboration environments, as users 91 must create separate profiles for each hosted instance. This simultaneously 92 limits a project’s exposure to the wider open source community, a key advantage 93 of platforms like GitHub, which have grown significantly due to network 94 effects. This isolation can impact the visibility and collaborative potential 95 of projects that choose traditional self-hosted solutions.</p> 96 97 <p>The Radicle protocol, in contrast, extends Git’s capabilities with a 98 decentralized identity system, novel gossip protocol, and integrated social 99 artifacts, forming a <em>self-hosted network for code collaboration</em>. Radicle 100 locates, serves, and replicates Git repositories – including artifacts – 101 across a <a href="https://en.wikipedia.org/wiki/Peer-to-peer">peer-to-peer</a> network while maintaining data authenticity via 102 cryptographic signatures, so peers can directly exchange data without the need 103 for a trusted third party. This enables communities to both self-host and share 104 their repositories across a distributed protocol, contributing to the emergence 105 of a new sovereign network for code collaboration and more.</p> 106 107 <h2 id="nodes">Nodes</h2> 108 109 <p>Radicle is a <a href="https://en.wikipedia.org/wiki/Peer-to-peer">peer-to-peer</a> system, which means that there is no traditional 110 client-server model. Peers on the Radicle network are referred to as <em>nodes</em>, 111 and are indistinguishable from users at the protocol level. Nodes, identified 112 by their <a href="#node-identifier-nid">Node ID</a> (NID) – an <a href="https://ed25519.cr.yp.to/">Ed25519</a> public 113 key – are responsible for seeding Git repositories, each identified by a unique 114 <a href="#repository-identifier-rid">Repository ID</a> (RID). The seeding process involves 115 both hosting the repository data and synchronizing changes with other nodes. 116 Every Radicle user, irrespective of their role or activity, runs a node on 117 their device. No specialized equipment is necessary for operating a node as a 118 typical end-user; nodes can run on a personal computer without requiring a 119 server.</p> 120 121 <aside> In the peer-to-peer model, nodes act as <em>both clients and 122 servers</em>. </aside> 123 124 <h3 id="seeding-repositories">Seeding Repositories</h3> 125 126 <p>Whenever a user clones, initializes, or opts to seed a repository, their node’s 127 seeding policy is changed to reflect their choices. This policy establishes the 128 repositories they are interested in and sets the rules for data retention, and 129 synchronization, allowing users to have direct control over which repositories 130 are kept on their device and offered to the network.</p> 131 132 <p>The typical end-user may choose to only seed the repositories they are actively 133 collaborating on. However, more dedicated users may opt to run an always-on 134 <strong>seed node</strong>, offering their infrastructure to the wider 135 Radicle network or to their community. Seed nodes significantly enhance the 136 network’s capacity to provide continuous access to a broad range of 137 repositories. They can vary in their seeding policies, from <em>public seed nodes</em> 138 that openly seed all repositories to <em>community seed nodes</em> that selectively 139 seed repositories from a group of trusted peers.</p> 140 141 <aside> For more details on how to run a seed node, refer to the <a href="https://docs.radicle.xyz/guides/seeder">Radicle Seeder's Guide</a> 142 </aside> 143 144 <h3 id="node-identifiers-nids">Node Identifiers (NIDs)</h3> 145 146 <aside class="kicker"> DIDs are a new identifier standard established by the 147 W3C. </aside> 148 149 <p>Radicle node identity is based on <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>, which makes 150 it easy to verify the authenticity of messages within the network through 151 <a href="https://en.wikipedia.org/wiki/Digital_signature">digital signatures</a>. This also allows for consistent identification 152 even as a user’s physical address varies. When setting up a node, users 153 generate their unique key pair, an <a href="https://ed25519.cr.yp.to/">Ed25519</a> public and private key, the 154 public part of which is encoded and shared as a <a href="https://www.w3.org/TR/did-core/">Decentralized Identifier</a> 155 (DID). Creating a node identity requires no permission or coordination: the key 156 pair can be created while offline without providing an email address or any 157 personal identifying information.</p> 158 159 <aside> DIDs enable verifiable, self-sovereign digital identities that are 160 fully under the control of the DID subject, independent of any centralized 161 registry, identity provider, or certificate authority. </aside> 162 163 <figure> 164 <pre class="center">did:key:<span class="highlight">z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK</span></pre> 165 <figcaption>Example Node ID encoded as a DID using the <a href="https://w3c-ccg.github.io/did-method-key/"><code>did:key</code> 166 method</a>.</figcaption> 167 </figure> 168 169 <p>It is important to safeguard one’s private key, as if it is either lost or 170 compromised, one will have to generate a new node identity. A changeable, 171 non-unique <strong>alias</strong> can optionally be associated to each node, for easier 172 human identification across the network.</p> 173 174 <aside> In the Radicle protocol, the terms "Node ID", "Peer ID", and "Public 175 Key" all refer to the same thing and can be used interchangeably. </aside> 176 177 <h3 id="running-a-node">Running a Node</h3> 178 179 <p>To run a node and connect to the network, users install Radicle client software 180 that is lightweight and suitable for use on both end-user devices and seed 181 nodes. The reference implementation can be found in the Radicle <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5">Heartwood</a> 182 repository, and is actively maintained by a small team of engineers.</p> 183 184 <aside> Radicle's reference implementation is written in <a href="https://www.rust-lang.org/">Rust</a>, a high-performance, memory-safe 185 language. </aside> 186 187 <p>The Radicle <em>stack</em> is comprised of both the network client and a command line 188 interface (CLI), which can be optionally supplemented with a web frontend. 189 Radicle is released under the open source MIT and Apache 2.0 licenses, to 190 encourage the development of diverse clients and applications. All client 191 software adheres to the Radicle protocol specification, as outlined in the 192 <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82">Radicle Improvement Proposals</a> (RIPs) repository, ensuring consistent 193 functionality across implementations.</p> 194 195 <aside> For a guided install of the Radicle stack, check out the <a href="#">user guide</a>. </aside> 196 197 <h2 id="peer-to-peer-protocol">Peer-to-peer Protocol</h2> 198 199 <p>Radicle adopts a local-first, peer-to-peer (P2P) architecture, which draws 200 inspiration from Secure Scuttlebutt (SSB) and Bitcoin’s <a href="https://en.wikipedia.org/wiki/Lightning_Network">Lightning 201 Network</a>.</p> 202 203 <p>Nodes on the Radicle network subscribe to repository data they are interested 204 in, and peers announce updates that in turn trigger fetches for the underlying 205 content. Just like SSB and Lightning, updates are <a href="https://en.wikipedia.org/wiki/Gossip_protocol">gossiped</a> on the 206 network until they reach all interested peers.</p> 207 208 <p>Peer connections in Radicle are secured thanks to a <a href="http://www.noiseprotocol.org/noise.html">Noise protocol</a> 209 handshake. Radicle uses the <a href="https://noiseexplorer.com/patterns/XK/">Noise XK</a> pattern specifically, just 210 like the Lightning Network with the Node ID as the <em>static key</em>. This requires 211 nodes to know the Node IDs of their peers before connecting to them, which 212 takes place through the exchange of peer information over the gossip protocol.</p> 213 214 <p>Unlike SSB’s focus on social networking via append-only logs, Radicle focuses 215 on code collaboration by incorporating Git’s <a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects">object model</a> and 216 <a href="https://git-scm.com/docs/pack-protocol/en">transfer protocol</a> into a peer-to-peer context. This architecture 217 not only leverages Git’s proven efficiency and reliability but also gives users 218 complete autonomy over their social artifacts. Radicle’s peer-to-peer 219 architecture, in contrast to federated systems, ensures no centralized points 220 of failure, allowing the network to persist as long as users operate nodes.</p> 221 222 <figure class="diagram"> 223 <object type="image/svg+xml" data="/assets/images/p2p-network.svg"></object> 224 <figcaption>A set of connected peers forming a gossip network.</figcaption> 225 </figure> 226 227 <h3 id="gossip-protocol">Gossip Protocol</h3> 228 229 <p>The Radicle networking layer is designed as a gossip protocol, where messages 230 are relayed between peers to build routing tables that aid in repository 231 discovery and replication. The core functionality is achieved with three 232 message types, each fulfilling a distinct role:</p> 233 234 <p><strong>Node Announcements</strong> are used for broadcasting Node IDs and physical 235 addresses on which a node is publicly reachable, to facilitate peer 236 discovery.</p> 237 238 <table> 239 <thead> 240 <tr> 241 <th>Node Announcement</th> 242 <th> </th> 243 <th> </th> 244 </tr> 245 </thead> 246 <tbody> 247 <tr> 248 <td><strong><code class="language-plaintext highlighter-rouge">version</code></strong></td> 249 <td><code class="language-plaintext highlighter-rouge">u8</code></td> 250 <td>Supported protocol version</td> 251 </tr> 252 <tr> 253 <td><strong><code class="language-plaintext highlighter-rouge">features</code></strong></td> 254 <td><code class="language-plaintext highlighter-rouge">u64</code></td> 255 <td>Advertised node capabilities</td> 256 </tr> 257 <tr> 258 <td><strong><code class="language-plaintext highlighter-rouge">timestamp</code></strong></td> 259 <td><code class="language-plaintext highlighter-rouge">u64</code></td> 260 <td>Message timestamp (unix time)</td> 261 </tr> 262 <tr> 263 <td><strong><code class="language-plaintext highlighter-rouge">alias</code></strong></td> 264 <td><code class="language-plaintext highlighter-rouge">u8[]</code></td> 265 <td>Non-unique alias (UTF-8)</td> 266 </tr> 267 <tr> 268 <td><strong><code class="language-plaintext highlighter-rouge">addresses</code></strong></td> 269 <td><code class="language-plaintext highlighter-rouge">Address[]</code></td> 270 <td>External addresses</td> 271 </tr> 272 <tr> 273 <td><strong><code class="language-plaintext highlighter-rouge">nonce</code></strong></td> 274 <td><code class="language-plaintext highlighter-rouge">u64</code></td> 275 <td>Nonce used for DoS protection</td> 276 </tr> 277 <tr> 278 <td><strong><code class="language-plaintext highlighter-rouge">agent</code></strong></td> 279 <td><code class="language-plaintext highlighter-rouge">u8[]</code></td> 280 <td>User-agent (UTF-8)</td> 281 </tr> 282 </tbody> 283 </table> 284 285 <p><strong>Inventory Announcements</strong> are used for broadcasting repository inventories 286 and constructing the routing table which maps out what repositories are 287 hosted where.</p> 288 289 <table> 290 <thead> 291 <tr> 292 <th>Inventory Announcement</th> 293 <th> </th> 294 <th> </th> 295 </tr> 296 </thead> 297 <tbody> 298 <tr> 299 <td><strong><code class="language-plaintext highlighter-rouge">inventory</code></strong></td> 300 <td><code class="language-plaintext highlighter-rouge">RepoID[]</code></td> 301 <td>Repository inventory</td> 302 </tr> 303 <tr> 304 <td><strong><code class="language-plaintext highlighter-rouge">timestamp</code></strong></td> 305 <td><code class="language-plaintext highlighter-rouge">u64</code></td> 306 <td>Message timestamp (unix time)</td> 307 </tr> 308 </tbody> 309 </table> 310 311 <p><strong>Reference Announcements</strong> are used for broadcasting updates to 312 repositories, relayed only to nodes interested in the relevant repository.</p> 313 314 <table> 315 <thead> 316 <tr> 317 <th>Refs Announcement</th> 318 <th> </th> 319 <th> </th> 320 </tr> 321 </thead> 322 <tbody> 323 <tr> 324 <td><strong><code class="language-plaintext highlighter-rouge">rid</code></strong></td> 325 <td><code class="language-plaintext highlighter-rouge">RepoID</code></td> 326 <td>Repository that was updated</td> 327 </tr> 328 <tr> 329 <td><strong><code class="language-plaintext highlighter-rouge">refs</code></strong></td> 330 <td><code class="language-plaintext highlighter-rouge">{NodeID, OID}[]</code></td> 331 <td>Updated signed refs (<code class="language-plaintext highlighter-rouge">rad/sigrefs</code>)</td> 332 </tr> 333 <tr> 334 <td><strong><code class="language-plaintext highlighter-rouge">timestamp</code></strong></td> 335 <td><code class="language-plaintext highlighter-rouge">u64</code></td> 336 <td>Message timestamp (unix time)</td> 337 </tr> 338 </tbody> 339 </table> 340 341 <aside> <code>OID</code> stands for <em>Object ID</em> and represents the SHA-1 342 hashes used by Git to identify objects.</aside> 343 344 <p>To prevent endless propagation, nodes drop any message already encountered. 345 However, for the sake of broadcasting messages to new nodes, gossip messages 346 may be temporarily stored and replayed to nodes joining the network for the 347 first time, or after a long period of being offline.</p> 348 349 <p>Each announcement includes the originating <em>Node ID</em> along with a 350 <em>cryptographic signature</em> and <em>timestamp</em>, allowing network participants to 351 verify the authenticity of messages before relaying them to peers.</p> 352 353 <figure> 354 <object type="image/svg+xml" data="/assets/images/announcement-msg.svg"></object> 355 <figcaption>Announcement message structure.</figcaption> 356 </figure> 357 358 <blockquote> 359 <p><strong>Tip</strong>: Refer to <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/tree/0001-heartwood.md">RIP-1</a> to learn more details about Radicle’s 360 networking protocol.</p> 361 </blockquote> 362 363 <h3 id="transport-encryption--privacy">Transport Encryption & Privacy</h3> 364 365 <p>Connections between peers in the Radicle network are encrypted using a <a href="http://www.noiseprotocol.org/noise.html">Noise</a> 366 protocol handshake. This begins with two peers performing a <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Hellman</a> key 367 exchange to agree on a shared session key that is used for the duration 368 of the connection.</p> 369 370 <p>Radicle uses the <a href="https://noiseexplorer.com/patterns/XK/">XK</a> handshake pattern, which requires the 371 connection responder’s <em>static key</em> to be known in advance by the initiator. 372 This <em>pre-sharing</em> takes place over the gossip network via the 373 <code class="language-plaintext highlighter-rouge">NodeAnnouncement</code> message, since the static key is simply the Node ID.</p> 374 375 <aside> The Noise framework calls the node that is receiving an inbound 376 connection the <em>responder</em>, and the node that is initiating the 377 connection the <em>initiator</em>. </aside> 378 379 <figure class="diagram"> 380 <object type="image/svg+xml" data="/assets/images/noisexk-1.svg"></object> 381 </figure> 382 383 <p>Once the static key is known, a connection to the node can be initiated 384 securely, by generating an ephemeral key from the static key, using 385 Diffie-Hellman. The last step involves the initiating node sending its own 386 static key over the secure channel.</p> 387 388 <figure class="diagram"> 389 <object type="image/svg+xml" data="/assets/images/noisexk-2.svg"></object> 390 </figure> 391 392 <p>After the handshake phase is completed, all data exchanged between peers is 393 fully encrypted and benefits from strong <a href="https://en.wikipedia.org/wiki/Forward_secrecy">forward secrecy</a>, ensuring 394 secure and private communications across the network.</p> 395 396 <blockquote> 397 <p><strong>Tip</strong>: Radicle also supports <a href="https://torproject.org/">Tor</a> addresses. Users can leverage Tor to 398 hide their IP address from peers, and connect to <code class="language-plaintext highlighter-rouge">.onion</code> addresses on the 399 Tor network.</p> 400 </blockquote> 401 402 <h3 id="replication-via-git">Replication via Git</h3> 403 404 <p>While gossip is used to exchange metadata, actual repository data is 405 transferred via replication using the <a href="https://git-scm.com/docs/pack-protocol/en">Git protocol</a>. The process 406 begins with a node establishing a secure connection to one or more of the 407 repository’s seeds, upon receiving a <em>reference</em> or <em>inventory</em> announcement of 408 interest.</p> 409 410 <p>Once connected, the node initiates a Git <em>fetch</em> protocol, which involves 411 negotiating which objects should be sent or skipped by the remote node. The 412 objects are then downloaded into the node’s storage, making them accessible to 413 other nodes via the same process.</p> 414 415 <p>Since Radicle uses a <a href="https://en.wikipedia.org/wiki/Frame_(networking)">framing</a> protocol for all its sessions, the fetch 416 protocol is able to take place over the same physical connection between nodes 417 as the gossip protocol. This allows for a more efficient use of resources 418 and avoids certain problems with <a href="https://en.wikipedia.org/wiki/Network_address_translation">NATs</a>. Although Git’s protocols are 419 typically connection-based, Radicle’s design allows for multiple concurrent 420 Git fetches to take place over a single connection.</p> 421 422 <aside> The idea of re-using a network connection for multiple concurrent 423 protocols is called <a href="https://en.wikipedia.org/wiki/Multiplexing">multiplexing</a>. </aside> 424 425 <figure class="diagram"> 426 <object type="image/svg+xml" data="/assets/images/multiplexing.svg"></object> 427 <figcaption>Connection multiplexing in Radicle.</figcaption> 428 </figure> 429 430 <h3 id="bootstrap-nodes">Bootstrap Nodes</h3> 431 432 <p>A node joining the network for the first time will not know any peers. Hence, 433 it’s useful to pre-configure network clients with addresses of well-known nodes 434 that can be used to initiate or <em>bootstrap</em> the peer discovery process and build 435 an address book.</p> 436 437 <p>Radicle’s reference implementation is pre-configured with two <a href="https://en.wikipedia.org/wiki/Bootstrapping_node">bootstrap 438 nodes</a> that are connected to if the address book is empty: 439 <a href="https://app.radicle.xyz/nodes/seed.radicle.garden">seed.radicle.garden</a> and <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz">seed.radicle.xyz</a>. These are nodes run by the 440 Radicle team and have large address books that are shared with connecting 441 peers.</p> 442 443 <p>In the bootstrapping process, nodes connect to an initial set of bootstrap nodes 444 and once they establish a connection, use the regular peer discovery mechanism 445 to find more peers.</p> 446 447 <h3 id="federation-vs-peer-to-peer">Federation vs. Peer-to-peer</h3> 448 449 <p>Federation allows for a degree of sovereignty, as each node can set its content 450 policies, but user experience and identity are ultimately tied and mediated by 451 these nodes’ administrators rather than by the users themselves.</p> 452 453 <blockquote> 454 <p><strong>federation</strong> /ˌfɛdəˈreɪʃn/ <em>n.</em></p> 455 456 <p><em>(Computing)</em> A system architecture where multiple independent servers or 457 nodes operate under a common set of standards and protocols, allowing them to 458 share data, resources, and functionalities across boundaries while 459 maintaining autonomy. This model enables interoperability and collective 460 services among diverse systems without fully centralizing control, thereby 461 enhancing privacy, scalability, and resilience. Each node in a federated 462 network can set its policies, manage its users, and control its data.</p> 463 </blockquote> 464 465 <aside> Examples of federated systems include <a href="https://atproto.com">AT 466 Protocol</a>, <a href="https://joinmastodon.org/">Mastodon</a> and plain old 467 E-mail. </aside> 468 469 <p>Although federated models promote a level of decentralization, they face unique 470 challenges, such as when node operators decide to block other nodes, taking 471 that choice away from its users and restricting the free flow of information.</p> 472 473 <p>Federated systems also face challenges related to incentives; specifically, 474 when the operational costs of maintaining a node exceed the perceived benefits, 475 node operators are often compelled to shut down. This can disrupt access for 476 users, undermining the platform’s reliability and the continuity of service.</p> 477 478 <p>While Radicle seed nodes face similar challenges, this has little bearing on 479 the end user: seed nodes are interchangeable and offer an undifferentiated 480 service; they are not tied to a user’s identity or access to the network.</p> 481 482 <figure class="diagram"> 483 <object type="image/svg+xml" data="/assets/images/federation-vs-p2p.svg"></object> 484 <figcaption>Federation (left) vs. peer-to-peer (right).</figcaption> 485 </figure> 486 487 <h2 id="repositories">Repositories</h2> 488 489 <p><strong>Repositories</strong> are central to the Radicle network, serving as the primary 490 data abstraction and object shared between peers. A repository in Radicle is 491 fundamentally a Git repository, supplemented with a unique repository 492 identifier (RID) and metadata essential for validating the authenticity of its 493 contents.</p> 494 495 <p>Radicle repositories, which can be either public or private, can accommodate 496 diverse content including source code, documentation, and arbitrary data sets. 497 All repositories are initialized with an <a href="#identity-document">identity 498 document</a> from which a unique Repository ID (RID) is 499 derived.</p> 500 501 <p>The identity document is where repository permissions and ownership are defined, 502 as well as identifying metadata such as name and description.</p> 503 504 <h3 id="delegates">Delegates</h3> 505 506 <p>Repositories are managed and owned by what are called <em>delegates</em>. A delegate 507 is an individual, group, or bot, identified by a <a href="https://www.w3.org/TR/did-core/">DID</a>. Delegates are 508 responsible for critical tasks such as merging patches, addressing issues, and 509 modifying repository permissions. A repository always begins with one delegate, 510 its creator, and can eventually grow to multiple delegates.</p> 511 512 <h3 id="identity-document">Identity Document</h3> 513 514 <p>Before a repository can be published on Radicle, it needs to be initialized 515 with an <em>identity document</em>. This JSON document, stored under the <code class="language-plaintext highlighter-rouge">refs/rad/id</code> 516 reference in Git, encapsulates key metadata such as the repository’s name, 517 description, and default branch. It also includes the DIDs of the 518 repository’s delegates and the <em>threshold</em> of delegate signatures required to 519 authorize changes to the repository’s default branch.</p> 520 521 <aside> The identity document is stored in Canonical JSON form. Canonical JSON 522 form standardizes JSON encoding to ensure identical byte representation for the 523 same data structures, making it particularly useful for cryptographic 524 operations like hashing. </aside> 525 526 <p>Here’s an example of the identity document for the <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5">heartwood</a> repository:</p> 527 528 <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> 529 </span><span class="nl">"delegates"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"</span><span class="p">],</span><span class="w"> 530 </span><span class="nl">"threshold"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> 531 </span><span class="nl">"payload"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> 532 </span><span class="nl">"xyz.radicle.project"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> 533 </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"heartwood"</span><span class="p">,</span><span class="w"> 534 </span><span class="nl">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Radicle Heartwood Protocol & Stack ❤️🪵"</span><span class="p">,</span><span class="w"> 535 </span><span class="nl">"defaultBranch"</span><span class="p">:</span><span class="w"> </span><span class="s2">"master"</span><span class="w"> 536 </span><span class="p">}</span><span class="w"> 537 </span><span class="p">}</span><span class="w"> 538 </span><span class="p">}</span><span class="w"> 539 </span></code></pre></div></div> 540 <h3 id="private-repositories">Private Repositories</h3> 541 542 <p>Radicle supports <strong>private repositories</strong> where access is restricted to a 543 designated group of trusted peers. This is achieved by setting the <code class="language-plaintext highlighter-rouge">visibility</code> 544 attribute in the identity document. For example, the following snippet sets 545 the visibility to <em>private</em>, while also allowing a specific peer to have 546 access to the repository.</p> 547 548 <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> 549 </span><span class="err">...</span><span class="w"> 550 </span><span class="nl">"visibility"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> 551 </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"private"</span><span class="p">,</span><span class="w"> 552 </span><span class="nl">"allow"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"</span><span class="p">]</span><span class="w"> 553 </span><span class="p">}</span><span class="w"> 554 </span><span class="p">}</span><span class="w"> 555 </span></code></pre></div></div> 556 557 <p>This ensures only nodes in the privacy set can replicate and access the data, 558 maintaining confidentiality. While the data is not encrypted at rest, these 559 repositories rely on selective replication through the <em>allow list</em> for 560 privacy, which renders them invisible and inaccessible to other nodes in the 561 Radicle network.</p> 562 563 <p>Note that repository delegates <em>always</em> have access to their private 564 repositories.</p> 565 566 <h3 id="repository-identifier-rid">Repository Identifier (RID)</h3> 567 568 <p>To ensure uniqueness and easy identification of repositories, a stable and 569 globally unique identifier, known as the Repository Identifier (RID), is 570 assigned to each repository. The RID is deterministically derived from the 571 initial version of the repository’s identity document. This process involves 572 using Git’s <code class="language-plaintext highlighter-rouge">hash-object</code> function to produce a 160-bit SHA-1 digest of the 573 document. This is then encoded using <a href="https://w3c-ccg.github.io/multibase/">multibase</a> encoding with the 574 <code class="language-plaintext highlighter-rouge">base-58-btc</code> alphabet, and prefixed with <code class="language-plaintext highlighter-rouge">rad:</code>, making it a valid <a href="https://datatracker.ietf.org/doc/html/rfc8141">URN</a>:</p> 575 576 <figure> 577 <pre class="center">rad:<span class="highlight">z3gqcJUoA1n9HaHKufZs5FCSGazv5</span></pre> 578 <figcaption>Example Repository ID for the heartwood project.</figcaption> 579 </figure> 580 581 <p>Since the RID is derived from the <em>initial</em> version of the repository’s identity 582 document, the document is able to change while the RID remains the same.</p> 583 584 <blockquote> 585 <p><strong>Tip</strong>: Refer to <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/tree/0002-identity.md">RIP-2</a> for more details about how repository 586 identity works in the Radicle protocol.</p> 587 </blockquote> 588 589 <!-- TODO: Add info about self-certifying updates --> 590 591 <h2 id="local-first-storage">Local-First Storage</h2> 592 593 <p>Storage is designed in such a way that it’s easy to transfer data between peers 594 over the network using an unmodified Git protocol. Radicle repositories are 595 simply Git repositories stored in a special location on disk. Peer data 596 is stored within the same repository using Git <a href="https://git-scm.com/docs/gitnamespaces">namespaces</a>, where Node 597 IDs are used as the namespace. This allows storage to be managed through a 598 partitioned approach where each user maintains their own <em>local fork</em> of a 599 repository, as well as any other forks they have an interest in, all within the 600 same Git repository. These forks are then shared among users across the 601 network.</p> 602 603 <p>Each repository fork has a <em>single owner and writer</em>, and users are only 604 permitted to make changes to their respective forks.</p> 605 606 <h3 id="working-vs-stored-copy">Working vs. Stored Copy</h3> 607 608 <p>Storage is accessed directly by the node to report its inventory to other 609 nodes, and by the end user through either specialized tooling or the <code class="language-plaintext highlighter-rouge">git</code> 610 command line tool. Users are typically interacting with two repository copies: 611 the <em>working copy</em>, and a remote <em>stored copy</em> that is interacted with via <code class="language-plaintext highlighter-rouge">git 612 push</code> and <code class="language-plaintext highlighter-rouge">git fetch</code>, using Radicle’s <a href="https://git-scm.com/docs/gitremote-helpers">git-remote-helper</a>.</p> 613 614 <p>This workflow is akin to what most developers are used to, when synchronizing 615 changes between their working copy, and the <code class="language-plaintext highlighter-rouge">origin</code> remote, which is typically 616 a repository on a hosted Git forge.</p> 617 618 <p>Changes to the stored copy are automatically propagated to the network when the 619 user is connected to the internet, but can also be made while offline. This 620 local-first design not only enhances the user experience by making offline work 621 frictionless, but also eliminates the need for centralized servers.</p> 622 623 <figure class="diagram"> 624 <object type="image/svg+xml" data="/assets/images/working-vs-stored.svg"></object> 625 <figcaption>Synchronizing the working copy with the stored copy of a repository.</figcaption> 626 </figure> 627 628 <h3 id="storage-layout">Storage Layout</h3> 629 630 <p>Radicle’s storage layout is designed to support multiple repositories and 631 multiple peers per repository. Each repository is a <em>bare</em> Git repository, 632 stored under a common base directory, identified uniquely with its Repository 633 ID or RID. Instead of each of the repository’s peers storing data in a separate 634 Git repository with a separate <a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects">object database</a> (ODB), peer data is 635 stored within the same Git repository using Git <a href="https://git-scm.com/docs/gitnamespaces">namespaces</a>.</p> 636 637 <aside> A <em>bare</em> Git repository is a repository stripped of its working 638 directory, containing only the version history (the contents of the 639 <code>.git</code> directory). It's used primarily as a remote repository that 640 developers can push to and pull from, but cannot directly edit files or commit 641 changes in. </aside> 642 643 <p>For each peer, including the local peer, their unique Node ID (NID) is used as 644 the namespace. Thus, each peer has its own namespaced references (eg. 645 <code class="language-plaintext highlighter-rouge">refs/heads</code>, and <code class="language-plaintext highlighter-rouge">refs/tags</code>), while sharing the underlying objects (i.e. 646 commits and blobs) with other namespaces via a shared object database. This 647 design ensures only one copy of each object is stored across all repository 648 forks.</p> 649 650 <p>Since the underlying storage uses Git, the storage layout below is represented 651 as a file tree on the file-system, with <code class="language-plaintext highlighter-rouge"><storage></code> representing the storage 652 root, or top-level directory under which all repositories are stored on a 653 user’s device. For every repository, each peer associated with that repository 654 must have a separate, logical Git source tree – which contains all the usual 655 reference categories. This <em>logical repository</em> is also known as the repository 656 <em>fork</em> or <em>view</em>, and allows nodes to maintain local data for all peers in the 657 same physical repository.</p> 658 659 <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><storage> # Storage root containing all repositories 660 ├─ <rid> # Storage for first repository 661 │ └─ refs # All Git references locally stored 662 │ └─ namespaces # All peer source trees or "forks" 663 │ ├─ <nid> # First node's source tree 664 │ │ └─ refs # First node's Git references 665 │ │ ├─ heads # First node's branches 666 │ │ │ └─ master # First node's master branch 667 │ │ └─ tags # First node's tags 668 │ │ 669 │ └─ <nid> # Second node's source tree 670 │ ├─ refs # Second node's references 671 │ └─ ... 672 ├─ <rid> # Storage for second repository 673 │ ... 674 └─ <rid> # etc. 675 ... 676 </code></pre></div></div> 677 678 <p>Though this storage tree is browsable by the user with standard file system 679 commands, it is not meant to be interacted with directly by users, for risk of 680 corrupting the data. Additionally, Git is free to pack the objects, which means 681 they may not always appear as individual files.</p> 682 683 <blockquote> 684 <p><strong>Tip</strong>: Refer to <a href="https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/tree/0003-storage-layout.md">RIP-3</a> to learn more about storage in the Radicle 685 protocol.</p> 686 </blockquote> 687 688 <h3 id="git-url-scheme">Git URL Scheme</h3> 689 690 <p>The Radicle protocol uses its own URL scheme to point to specific repository 691 forks in the network. This allows the Git <code class="language-plaintext highlighter-rouge">fetch</code> and <code class="language-plaintext highlighter-rouge">push</code> commands to 692 operate on the correct namespace when fetching or pushing code.</p> 693 694 <figure> 695 <pre class="center">rad://<span class="highlight">z42hL2jL4XNk6K8oHQaSWfMgCL7ji</span>/<span class="highlight-secondary">z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi</span></pre> 696 <figcaption> Example URL for repository <code>z42hL2jL4XNk6K8oHQaSWfMgCL7ji</code> and 697 peer <code>z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi</code>. </figcaption> 698 </figure> 699 700 <p>The Radicle <a href="https://git-scm.com/docs/gitremote-helpers">remote helper</a> is what allows Git to interpret URLs with the 701 <code class="language-plaintext highlighter-rouge">rad://</code> scheme. By using this scheme, the user instructs Git to 702 invoke the <code class="language-plaintext highlighter-rouge">git-remote-rad</code> executable during <code class="language-plaintext highlighter-rouge">git push</code> or <code class="language-plaintext highlighter-rouge">git fetch</code>, which 703 allows the user to interact with the network through the storage layer.</p> 704 705 <p>For example, the above URL would map a push to the <code class="language-plaintext highlighter-rouge">master</code> branch to the following 706 path under the local storage root:</p> 707 708 <pre> 709 /<span class="highlight">z42hL2jL4XNk6K8oHQaSWfMgCL7ji</span>/refs/namespaces/<span class="highlight-secondary">z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi</span>/refs/heads/master 710 </pre> 711 712 <p>If a Node ID is not specified in the URL, Git will interact with the 713 repository’s <a href="#Canonical-Repository-Version">canonical references</a>, also know 714 as the authoritative repository state. This is the state agreed on by the 715 repository <a href="#delegates">delegates</a>.</p> 716 717 <figure> 718 <pre class="center">rad://<span class="highlight">z42hL2jL4XNk6K8oHQaSWfMgCL7ji</span></pre> 719 <figcaption> Example URL for repository 720 <code>z42hL2jL4XNk6K8oHQaSWfMgCL7ji</code>'s canonical 721 references.</figcaption> 722 </figure> 723 724 <h2 id="trust-through-self-certification">Trust through Self-Certification</h2> 725 726 <p>Unlike centralized forges such as GitHub, where repositories are deemed 727 authentic based on their location (e.g. <code class="language-plaintext highlighter-rouge">https://github.com/bitcoin/bitcoin</code>), 728 in a decentralized network like Radicle, location is not enough. Instead, we 729 need a way to automatically verify the data we get from <em>any given location</em>. 730 This is because peers in a decentralized network may be dishonest. Radicle’s 731 approach hinges on the self-certifying nature of its repositories, anchored in 732 the repository <a href="#identity-document">identity document</a>.</p> 733 734 <h3 id="canonical-branches">Canonical Branches</h3> 735 736 <p>When repositories are hosted in a known, trusted location, updating the 737 repository’s canonical branch (eg. <code class="language-plaintext highlighter-rouge">master</code>) is simply a matter of pushing 738 to that repository’s branch. Permission to push is granted to a small set 739 of maintainers, and any one maintainer is allowed to update the branch.</p> 740 741 <p>In Radicle, lacking a central location where repositories are hosted, the 742 canonical branch is established <em>dynamically</em> based on the signature 743 <strong>threshold</strong> defined in the repository’s identity document. For example, if a 744 threshold of two out of three delegates is set, with the default branch set to 745 <code class="language-plaintext highlighter-rouge">master</code>, and two delegates have pushed the same commit to their <code class="language-plaintext highlighter-rouge">master</code> 746 branches, that commit is recognized as the authoritative, canonical state of 747 the repository.</p> 748 749 <blockquote> 750 <p><strong>Note</strong>: Currently, only the branch specified under the <code class="language-plaintext highlighter-rouge">defaultBranch</code> 751 attribute of the identity document is set automatically based on a signature 752 threshold. In the future, additional branches may be supported.</p> 753 </blockquote> 754 755 <h3 id="self-certifying-repositories">Self-certifying Repositories</h3> 756 757 <p>Together, a repository’s RID and its identity document create a cryptographic 758 proof that serves as the basis for verifying all repository states leading 759 up to its current state. For this reason, we say that Radicle repositories 760 are <em>self-certifying</em>: the process of verification doesn’t require any 761 inputs other than the repository itself.</p> 762 763 <p>For repositories to be self-certifying, delegates authenticate every change to 764 the repository data and metadata via cryptographic signatures. This includes 765 all Git references published to the network.</p> 766 767 <!-- TODO: Copy section from RIP-2 --> 768 769 <h4 id="signed-refs">Signed Refs</h4> 770 771 <p>To enable the verification of Git references beyond commits to the source code, 772 Radicle automatically signs the entirety of a node’s references every time they 773 change. This signature is then placed in a Git blob under a special branch 774 referenced under <code class="language-plaintext highlighter-rouge">refs/rad/sigrefs</code>, along with the references that were signed.</p> 775 776 <figure> 777 <pre>9767b485c2aad1e23097d2b5165287ba84cfa452 refs/heads/master 778 f3eaa7454e3a4714885905ae99f616fc7895b5fa refs/cobs/xyz.radicle.patch/fe31d5b6049583a42c21a543545d182b893aa4a0 779 0590b78ee42b39087983e4de04164065e5aa11bc refs/cobs/xyz.radicle.patch/ffbb812ad6e7fe1c5c610b1246ca5ca9d7d16027</pre> 780 <figcaption>Example <code>refs</code> blob under a user's <code>refs/rad/sigrefs</code> branch. 781 </figcaption> 782 </figure> 783 784 <aside> The signed references are in the same format as the <code>git 785 show-ref</code> command. </aside> 786 787 <p>Signed refs are key to establishing a repository’s canonical state and are 788 updated whenever there are changes to a repository.</p> 789 790 <p>Given an RID and a Radicle repository clone, anyone can retrieve the initial 791 identity document and authenticate all subsequent repository updates without a 792 trusted third party. This verification model draws inspiration from <a href="https://theupdateframework.github.io/specification/latest/">The Update 793 Framework</a> (TUF), a framework designed to secure software update systems.</p> 794 795 <h2 id="collaborative-objects">Collaborative Objects</h2> 796 797 <p>In the Radicle protocol, Collaborative Objects (COBs) play an important role in 798 supplementing Git with social artifacts such as issues, code reviews and 799 discussions, which are not inherently supported by Git. Typically, these 800 artifacts are only found on centralized platforms like GitHub or GitLab, or 801 their self-hosted counterparts.</p> 802 803 <p>In Radicle, COBs allow for social artifacts to be stored directly inside a 804 repository, and replicated between peers. This means that social artifacts 805 inherit the same properties as source code: they are local-first, user-owned, 806 and cryptographically signed.</p> 807 808 <p>Radicle includes three predefined collaborative object types to support code 809 collaboration: <em>Issues</em>, <em>Patches</em>, and <em>Identities</em>, but users have full 810 control to customize them or extend Radicle with entirely new COB types.</p> 811 812 <ul> 813 <li><strong>Issues</strong> (<code class="language-plaintext highlighter-rouge">xyz.radicle.issue</code>) are used for tracking bugs or feature 814 requests, and support discussions, labeling and assigning.</li> 815 <li><strong>Patches</strong> (<code class="language-plaintext highlighter-rouge">xyz.radicle.patch</code>) are used to propose changes to a 816 branch, and support reviews, versioning of changes and discussions.</li> 817 <li><strong>Identities</strong> (<code class="language-plaintext highlighter-rouge">xyz.radicle.id</code>) are used to represent identity documents.</li> 818 </ul> 819 820 <aside> The repository's identity document is entirely defined and managed 821 through an <em>id</em> COB. </aside> 822 823 <p>COBs are identified by a unique type name in <a href="https://en.wikipedia.org/wiki/Reverse_domain_name_notation">reverse domain name 824 notation</a> and a unique Object ID.</p> 825 826 <h3 id="concurrency--consistency">Concurrency & Consistency</h3> 827 828 <p>In a system with no central server, operation concurrency is the norm. If 829 two users comment on an issue at the same time, those comments will reach 830 peers in the network at different times and in different orders. To maintain 831 a good user experience, it’s important that these factors don’t determine 832 the issue’s final state. All users must eventually converge to the same exact 833 state and see the same thing.</p> 834 835 <p>To achieve this, Radicle makes use of Git’s native synchronization primitives, 836 and encodes COBs as a set of commits in a <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">directed acyclic graph</a> (DAG). 837 Each issue, patch or identity document is represented by one such commit graph 838 that is disjoint from any other COB or source code branch.</p> 839 840 <p>This representation gives Radicle a few things for free:</p> 841 842 <ol> 843 <li>Data integrity is guaranteed by Git.</li> 844 <li>Synchronization is handled by Git.</li> 845 <li>Causal dependencies can be modeled as commit parent-child relationships.</li> 846 </ol> 847 848 <p>It may be useful to think of Radicle’s usage of Git commit histories as a 849 form of <a href="https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type">conflict-free replicated data type</a> (CRDT). When the histories 850 of two peers are synchronized, the commit graphs are simply <em>unioned</em> with 851 each other in a non-destructive, idempotent way.</p> 852 853 <aside> <strong>Idempotence</strong> is the property of certain operations in 854 mathematics and computer science whereby they can be applied multiple times 855 without changing the result. </aside> 856 857 <aside class="diagram span-2"> 858 <p> 859 Git DAG representing an Issue COB. Each box represents a 860 commit object with a change to the COB. 861 </p> 862 <p> 863 The different colors represent different 864 commit authors and the arrows represent commit parents, or causal 865 dependencies. 866 </p> 867 </aside> 868 869 <figure class="diagram tall"> 870 <object type="image/svg+xml" data="/assets/images/cob-dag.svg"></object> 871 </figure> 872 873 <p>Then, to materialize the state that is displayed to the user, this new graph is 874 <em>reduced</em> in <a href="https://en.wikipedia.org/wiki/Topological_sorting">topological order</a>, starting from the root of the graph and 875 going up to the tips. This ordering happens to be <a href="https://en.wikipedia.org/wiki/Causal_consistency">causally 876 consistent</a>, ensuring that changes that have observed other changes 877 are traversed in causal order. Since topological ordering may yield <em>partial</em> 878 orders in the face of concurrency, a merge function is also defined, the 879 simplest of which is to traverse the partially-ordered graph vertices sorted by 880 their commit hash. If a merge function cannot be defined, a COB may be 881 configured to treat this as a <em>conflict</em> which can be bubbled up to the user.</p> 882 883 <aside> A <em>reduce</em> or <em>fold</em> operation is a way of getting a 884 single value by applying a function to a list of values. </aside> 885 886 <p>In summary, this mechanism supports multiple users independently interacting 887 without coordination. Each COB records the initial version of an object and 888 tracks all subsequent modifications made across the network. Each modification 889 is stored as a separate Git <em>commit</em> object to ensure that the CRDT change 890 graph is compatible with Git’s fetch protocol. To retrieve the current state of 891 an object, the system replays all the changes to the object in a deterministic 892 and causally-consistent order.</p> 893 894 <h3 id="extending-cobs">Extending COBs</h3> 895 896 <p>Radicle’s predefined COB types are stored under the <code class="language-plaintext highlighter-rouge">refs/cobs</code> hierarchy. 897 These are associated with unique namespaces, such as <code class="language-plaintext highlighter-rouge">xyz.radicle.issue</code> and 898 <code class="language-plaintext highlighter-rouge">xyz.radicle.patch</code>, to prevent naming collisions.</p> 899 900 <p>This hierarchical arrangement under <code class="language-plaintext highlighter-rouge">refs/cobs</code> not only houses Radicle’s 901 predefined COBs but also accommodates user-defined ones. For example, if a user 902 or organization were to define a new COB type under their domain, it might look 903 something like <code class="language-plaintext highlighter-rouge">com.acme.task</code>, for some hypothetical “task” COB under the 904 <code class="language-plaintext highlighter-rouge">acme.com</code> domain.</p> 905 906 <p>This extensibility allows for an unlimited set of new collaboration primitives 907 to be defined by users, without requiring coordination with the broader network 908 or user-base.</p> 909 910 <h2 id="conclusion">Conclusion</h2> 911 912 <p>The Radicle Heartwood protocol introduces a new approach to code collaboration 913 and hosting rooted in sovereignty. Built upon Git’s well-established protocol, 914 Radicle can easily interoperate with existing systems and workflows that are 915 already familiar. Users have full control and ownership over their identity and 916 data. Repositories are self-certifying data structures, meaning updates are 917 cryptographically signed and can be verified by anyone, without needing a 918 trusted third party. Every user in Radicle is self-hosting while remaining 919 connected to a wider network. Radicle is highly extensible with its 920 Collaborative Objects that enable full control and customization over workflows 921 and datatypes, while also opening the possibility for Radicle to support a 922 wider range of functionalities, potentially extending far beyond code 923 collaboration.</p> 924 925 <!-- References --> 926 927 928 </main> 929 <footer> 930 <p>© The Radicle Team</p> 931 </footer> 932 <script src="/assets/js/toggle-theme.js"></script> 933 </body> 934 </html>