/ docs / Radicle Protocol Guide.html
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 &amp; 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 &amp; 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 &amp; 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 &amp; 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">&lt;storage&gt;</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>&lt;storage&gt;                     # Storage root containing all repositories
660  ├─ &lt;rid&gt;                      # Storage for first repository
661  │  └─ refs                    # All Git references locally stored
662  │     └─ namespaces           # All peer source trees or "forks"
663  │        ├─ &lt;nid&gt;             # 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  │        └─ &lt;nid&gt;             # Second node's source tree
670  │           ├─ refs           # Second node's references
671  │           └─ ...
672  ├─ &lt;rid&gt;                      # Storage for second repository
673  │   ...
674  └─ &lt;rid&gt;                      # 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 &amp; 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>&copy; The Radicle Team</p>
931      </footer>
932      <script src="/assets/js/toggle-theme.js"></script>
933    </body>
934  </html>