Radish alpha
r
rad:z371PVmDHdjJucejRoRYJcDEvD5pp
Radicle website including documentation and guides
Radicle
Git
chore: fix broken 'docs.' urls for radicle.xyz
Merged ade opened 6 months ago

Two broken urls in protocol guide updated.

1 file changed +59 -61 f4fb299d 429410b8
modified _guides/protocol.md
@@ -58,7 +58,7 @@ of projects that choose traditional self-hosted solutions.

The Radicle protocol, in contrast, extends Git's capabilities with a
decentralized identity system, novel gossip protocol, and integrated social
-
artifacts, forming a *self-hosted network for code collaboration*. Radicle
+
artifacts, forming a _self-hosted network for code collaboration_. Radicle
locates, serves, and replicates Git repositories -- including artifacts --
across a [peer-to-peer] network while maintaining data authenticity via
cryptographic signatures, so peers can directly exchange data without the need
@@ -69,7 +69,7 @@ of a new sovereign network for code collaboration and more.
## Nodes

Radicle is a [peer-to-peer] system, which means that there is no traditional
-
client-server model. Peers on the Radicle network are referred to as *nodes*,
+
client-server model. Peers on the Radicle network are referred to as _nodes_,
and are indistinguishable from users at the protocol level. Nodes, identified
by their [Node ID](#node-identifier-nid) (NID) -- an [Ed25519] public
key -- are responsible for seeding Git repositories, each identified by a unique
@@ -96,12 +96,12 @@ collaborating on. However, more dedicated users may opt to run an always-on
**seed node**, offering their infrastructure to the wider
Radicle network or to their community. Seed nodes significantly enhance the
network's capacity to provide continuous access to a broad range of
-
repositories. They can vary in their seeding policies, from *public seed nodes*
-
that openly seed all repositories to *community seed nodes* that selectively
+
repositories. They can vary in their seeding policies, from _public seed nodes_
+
that openly seed all repositories to _community seed nodes_ that selectively
seed repositories from a group of trusted peers.

<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>
+
href="https://radicle.xyz/guides/seeder">Radicle Seeder's Guide</a>
</aside>

### Node Identifiers (NIDs)
@@ -149,7 +149,7 @@ repository, and is actively maintained by a small team of engineers.
href="https://www.rust-lang.org/">Rust</a>, a high-performance, memory-safe
language. </aside>

-
The Radicle *stack* is comprised of both the network client and a command line
+
The Radicle _stack_ is comprised of both the network client and a command line
interface (CLI), which can be optionally supplemented with a web frontend.
Radicle is released under the open source MIT and Apache 2.0 licenses, to
encourage the development of diverse clients and applications. All client
@@ -173,7 +173,7 @@ network until they reach all interested peers.

Peer connections in Radicle are secured thanks to a [Noise protocol][noise]
handshake. Radicle uses the [Noise XK][noise-xk] pattern specifically, just
-
like the Lightning Network with the Node ID as the *static key*. This requires
+
like the Lightning Network with the Node ID as the _static key_. This requires
nodes to know the Node IDs of their peers before connecting to them, which
takes place through the exchange of peer information over the gossip protocol.

@@ -198,36 +198,36 @@ discovery and replication. The core functionality is achieved with three
message types, each fulfilling a distinct role:

**Node Announcements** are used for broadcasting Node IDs and physical
-
   addresses on which a node is publicly reachable, to facilitate peer
-
   discovery.
+
addresses on which a node is publicly reachable, to facilitate peer
+
discovery.

| Node Announcement
| -----------------
-
| **`version`**   | `u8`             | Supported protocol version
-
| **`features`**  | `u64`            | Advertised node capabilities
-
| **`timestamp`** | `u64`            | Message timestamp (unix time)
-
| **`alias`**     | `u8[]`           | Non-unique alias (UTF-8)
-
| **`addresses`** | `Address[]`      | External addresses
-
| **`nonce`**     | `u64`            | Nonce used for DoS protection
-
| **`agent`**     | `u8[]`           | User-agent (UTF-8)
+
| **`version`** | `u8` | Supported protocol version
+
| **`features`** | `u64` | Advertised node capabilities
+
| **`timestamp`** | `u64` | Message timestamp (unix time)
+
| **`alias`** | `u8[]` | Non-unique alias (UTF-8)
+
| **`addresses`** | `Address[]` | External addresses
+
| **`nonce`** | `u64` | Nonce used for DoS protection
+
| **`agent`** | `u8[]` | User-agent (UTF-8)

**Inventory Announcements** are used for broadcasting repository inventories
-
   and constructing the routing table which maps out what repositories are
-
   hosted where.
+
and constructing the routing table which maps out what repositories are
+
hosted where.

| Inventory Announcement
| ----------------------
| **`inventory`** | `RepoID[]` | Repository inventory
-
| **`timestamp`** | `u64`      | Message timestamp (unix time)
+
| **`timestamp`** | `u64` | Message timestamp (unix time)

**Reference Announcements** are used for broadcasting updates to
-
   repositories, relayed only to nodes interested in the relevant repository.
+
repositories, relayed only to nodes interested in the relevant repository.

| Refs Announcement
| -----------------
-
| **`rid`**        | `RepoID`          | Repository that was updated
-
| **`refs`**       | `{NodeID, OID}[]` | Updated signed refs (`rad/sigrefs`)
-
| **`timestamp`**  | `u64`             | Message timestamp (unix time)
+
| **`rid`** | `RepoID` | Repository that was updated
+
| **`refs`** | `{NodeID, OID}[]` | Updated signed refs (`rad/sigrefs`)
+
| **`timestamp`** | `u64` | Message timestamp (unix time)

<aside> <code>OID</code> stands for <em>Object ID</em> and represents the SHA-1
hashes used by Git to identify objects.</aside>
@@ -237,8 +237,8 @@ However, for the sake of broadcasting messages to new nodes, gossip messages
may be temporarily stored and replayed to nodes joining the network for the
first time, or after a long period of being offline.

-
Each announcement includes the originating *Node ID* along with a
-
*cryptographic signature* and *timestamp*, allowing network participants to
+
Each announcement includes the originating _Node ID_ along with a
+
_cryptographic signature_ and _timestamp_, allowing network participants to
verify the authenticity of messages before relaying them to peers.

<figure>
@@ -257,8 +257,8 @@ exchange to agree on a shared session key that is used for the duration
of the connection.

Radicle uses the [XK][noise-xk] handshake pattern, which requires the
-
connection responder's *static key* to be known in advance by the initiator.
-
This *pre-sharing* takes place over the gossip network via the
+
connection responder's _static key_ to be known in advance by the initiator.
+
This _pre-sharing_ takes place over the gossip network via the
`NodeAnnouncement` message, since the static key is simply the Node ID.

<aside> The Noise framework calls the node that is receiving an inbound
@@ -291,10 +291,10 @@ secure and private communications across the network.
While gossip is used to exchange metadata, actual repository data is
transferred via replication using the [Git protocol][git-pack]. The process
begins with a node establishing a secure connection to one or more of the
-
repository's seeds, upon receiving a *reference* or *inventory* announcement of
+
repository's seeds, upon receiving a _reference_ or _inventory_ announcement of
interest.

-
Once connected, the node initiates a Git *fetch* protocol, which involves
+
Once connected, the node initiates a Git _fetch_ protocol, which involves
negotiating which objects should be sent or skipped by the remote node. The
objects are then downloaded into the node's storage, making them accessible to
other nodes via the same process.
@@ -319,7 +319,7 @@ href="https://en.wikipedia.org/wiki/Multiplexing">multiplexing</a>. </aside>

A node joining the network for the first time will not know any peers. Hence,
it's useful to pre-configure network clients with addresses of well-known nodes
-
that can be used to initiate or *bootstrap* the peer discovery process and build
+
that can be used to initiate or _bootstrap_ the peer discovery process and build
an address book.

Radicle's reference implementation is pre-configured with two [bootstrap
@@ -340,9 +340,9 @@ Federation allows for a degree of sovereignty, as each node can set its content
policies, but user experience and identity are ultimately tied and mediated by
these nodes' administrators rather than by the users themselves.

-
> **federation** /ˌfɛdəˈreɪʃn/ *n.*
+
> **federation** /ˌfɛdəˈreɪʃn/ _n._
>
-
> *(Computing)* A system architecture where multiple independent servers or
+
> _(Computing)_ A system architecture where multiple independent servers or
> nodes operate under a common set of standards and protocols, allowing them to
> share data, resources, and functionalities across boundaries while
> maintaining autonomy. This model enables interoperability and collective
@@ -391,7 +391,7 @@ as well as identifying metadata such as name and description.

### Delegates

-
Repositories are managed and owned by what are called *delegates*. A delegate
+
Repositories are managed and owned by what are called _delegates_. A delegate
is an individual, group, or bot, identified by a [DID][did]. Delegates are
responsible for critical tasks such as merging patches, addressing issues, and
modifying repository permissions. A repository always begins with one delegate,
@@ -400,10 +400,10 @@ its creator, and can eventually grow to multiple delegates.
### Identity Document

Before a repository can be published on Radicle, it needs to be initialized
-
with an *identity document*. This JSON document, stored under the `refs/rad/id`
+
with an _identity document_. This JSON document, stored under the `refs/rad/id`
reference in Git, encapsulates key metadata such as the repository’s name,
description, and default branch. It also includes the DIDs of the
-
repository's delegates and the *threshold* of delegate signatures required to
+
repository's delegates and the _threshold_ of delegate signatures required to
authorize changes to the repository's default branch.

<aside> The identity document is stored in Canonical JSON form. Canonical JSON
@@ -426,12 +426,13 @@ Here's an example of the identity document for the [heartwood] repository:
  }
}
```
+

### Private Repositories

Radicle supports **private repositories** where access is restricted to a
designated group of trusted peers. This is achieved by setting the `visibility`
attribute in the identity document. For example, the following snippet sets
-
the visibility to *private*, while also allowing a specific peer to have
+
the visibility to _private_, while also allowing a specific peer to have
access to the repository.

```json
@@ -446,11 +447,11 @@ access to the repository.

This ensures only nodes in the privacy set can replicate and access the data,
maintaining confidentiality. While the data is not encrypted at rest, these
-
repositories rely on selective replication through the *allow list* for
+
repositories rely on selective replication through the _allow list_ for
privacy, which renders them invisible and inaccessible to other nodes in the
Radicle network.

-
Note that repository delegates *always* have access to their private
+
Note that repository delegates _always_ have access to their private
repositories.

### Repository Identifier (RID)
@@ -468,7 +469,7 @@ document. This is then encoded using [multibase][mb] encoding with the
  <figcaption>Example Repository ID for the heartwood project.</figcaption>
</figure>

-
Since the RID is derived from the *initial* version of the repository's identity
+
Since the RID is derived from the _initial_ version of the repository's identity
document, the document is able to change while the RID remains the same.

[urn]: https://datatracker.ietf.org/doc/html/rfc8141
@@ -486,12 +487,12 @@ over the network using an unmodified Git protocol. Radicle repositories are
simply Git repositories stored in a special location on disk. Peer data
is stored within the same repository using Git [namespaces][gns], where Node
IDs are used as the namespace. This allows storage to be managed through a
-
partitioned approach where each user maintains their own *local fork* of a
+
partitioned approach where each user maintains their own _local fork_ of a
repository, as well as any other forks they have an interest in, all within the
same Git repository. These forks are then shared among users across the
network.

-
Each repository fork has a *single owner and writer*, and users are only
+
Each repository fork has a _single owner and writer_, and users are only
permitted to make changes to their respective forks.

### Working vs. Stored Copy
@@ -499,7 +500,7 @@ permitted to make changes to their respective forks.
Storage is accessed directly by the node to report its inventory to other
nodes, and by the end user through either specialized tooling or the `git`
command line tool. Users are typically interacting with two repository copies:
-
the *working copy*, and a remote *stored copy* that is interacted with via `git
+
the _working copy_, and a remote _stored copy_ that is interacted with via `git
push` and `git fetch`, using Radicle's [git-remote-helper][grh].

This workflow is akin to what most developers are used to, when synchronizing
@@ -516,11 +517,10 @@ frictionless, but also eliminates the need for centralized servers.
  <figcaption>Synchronizing the working copy with the stored copy of a repository.</figcaption>
</figure>

-

### Storage Layout

Radicle's storage layout is designed to support multiple repositories and
-
multiple peers per repository. Each repository is a *bare* Git repository,
+
multiple peers per repository. Each repository is a _bare_ Git repository,
stored under a common base directory, identified uniquely with its Repository
ID or RID. Instead of each of the repository's peers storing data in a separate
Git repository with a separate [object database][git-odb] (ODB), peer data is
@@ -544,8 +544,8 @@ as a file tree on the file-system, with `<storage>` representing the storage
root, or top-level directory under which all repositories are stored on a
user's device. For every repository, each peer associated with that repository
must have a separate, logical Git source tree -- which contains all the usual
-
reference categories. This *logical repository* is also known as the repository
-
*fork* or *view*, and allows nodes to maintain local data for all peers in the
+
reference categories. This _logical repository_ is also known as the repository
+
_fork_ or _view_, and allows nodes to maintain local data for all peers in the
same physical repository.

```
@@ -568,7 +568,6 @@ same physical repository.
    ...
```

-

Though this storage tree is browsable by the user with standard file system
commands, it is not meant to be interacted with directly by users, for risk of
corrupting the data. Additionally, Git is free to pack the objects, which means
@@ -613,13 +612,12 @@ repository [delegates](#delegates).
  references.</figcaption>
</figure>

-

## Trust through Self-Certification

Unlike centralized forges such as GitHub, where repositories are deemed
authentic based on their location (e.g. `https://github.com/bitcoin/bitcoin`),
in a decentralized network like Radicle, location is not enough. Instead, we
-
need a way to automatically verify the data we get from *any given location*.
+
need a way to automatically verify the data we get from _any given location_.
This is because peers in a decentralized network may be dishonest. Radicle's
approach hinges on the self-certifying nature of its repositories, anchored in
the repository [identity document](#identity-document).
@@ -632,7 +630,7 @@ to that repository's branch. Permission to push is granted to a small set
of maintainers, and any one maintainer is allowed to update the branch.

In Radicle, lacking a central location where repositories are hosted, the
-
canonical branch is established *dynamically* based on the signature
+
canonical branch is established _dynamically_ based on the signature
**threshold** defined in the repository's identity document. For example, if a
threshold of two out of three delegates is set, with the default branch set to
`master`, and two delegates have pushed the same commit to their `master`
@@ -648,7 +646,7 @@ the repository.
Together, a repository's RID and its identity document create a cryptographic
proof that serves as the basis for verifying all repository states leading
up to its current state. For this reason, we say that Radicle repositories
-
are *self-certifying*: the process of verification doesn't require any
+
are _self-certifying_: the process of verification doesn't require any
inputs other than the repository itself.

For repositories to be self-certifying, delegates authenticate every change to
@@ -697,14 +695,14 @@ inherit the same properties as source code: they are local-first, user-owned,
and cryptographically signed.

Radicle includes three predefined collaborative object types to support code
-
collaboration: *Issues*, *Patches*, and *Identities*, but users have full
+
collaboration: _Issues_, _Patches_, and _Identities_, but users have full
control to customize them or extend Radicle with entirely new COB types.

-
* **Issues** (`xyz.radicle.issue`) are used for tracking bugs or feature
+
- **Issues** (`xyz.radicle.issue`) are used for tracking bugs or feature
  requests, and support discussions, labeling and assigning.
-
* **Patches** (`xyz.radicle.patch`) are used to propose changes to a
+
- **Patches** (`xyz.radicle.patch`) are used to propose changes to a
  branch, and support reviews, versioning of changes and discussions.
-
* **Identities** (`xyz.radicle.id`) are used to represent identity documents.
+
- **Identities** (`xyz.radicle.id`) are used to represent identity documents.

<aside> The repository's identity document is entirely defined and managed
through an <em>id</em> COB. </aside>
@@ -734,7 +732,7 @@ This representation gives Radicle a few things for free:

It may be useful to think of Radicle's usage of Git commit histories as a
form of [conflict-free replicated data type][crdt] (CRDT). When the histories
-
of two peers are synchronized, the commit graphs are simply *unioned* with
+
of two peers are synchronized, the commit graphs are simply _unioned_ with
each other in a non-destructive, idempotent way.

<aside> <strong>Idempotence</strong> is the property of certain operations in
@@ -758,14 +756,14 @@ without changing the result. </aside>
</figure>

Then, to materialize the state that is displayed to the user, this new graph is
-
*reduced* in [topological order][topo], starting from the root of the graph and
+
_reduced_ in [topological order][topo], starting from the root of the graph and
going up to the tips. This ordering happens to be [causally
consistent][causality], ensuring that changes that have observed other changes
-
are traversed in causal order. Since topological ordering may yield *partial*
+
are traversed in causal order. Since topological ordering may yield _partial_
orders in the face of concurrency, a merge function is also defined, the
simplest of which is to traverse the partially-ordered graph vertices sorted by
their commit hash. If a merge function cannot be defined, a COB may be
-
configured to treat this as a *conflict* which can be bubbled up to the user.
+
configured to treat this as a _conflict_ which can be bubbled up to the user.

<aside> A <em>reduce</em> or <em>fold</em> operation is a way of getting a
single value by applying a function to a list of values. </aside>
@@ -773,7 +771,7 @@ single value by applying a function to a list of values. </aside>
In summary, this mechanism supports multiple users independently interacting
without coordination. Each COB records the initial version of an object and
tracks all subsequent modifications made across the network. Each modification
-
is stored as a separate Git *commit* object to ensure that the CRDT change
+
is stored as a separate Git _commit_ object to ensure that the CRDT change
graph is compatible with Git's fetch protocol. To retrieve the current state of
an object, the system replays all the changes to the object in a deterministic
and causally-consistent order.
@@ -845,7 +843,7 @@ collaboration.
[rips]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82
[heartwood]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
[did]: https://www.w3.org/TR/did-core/
-
[seed]: https://docs.radicle.xyz/guides/seeder/
+
[seed]: https://radicle.xyz/guides/seeder/
[peer-to-peer]: https://en.wikipedia.org/wiki/Peer-to-peer
[forges]: https://en.wikipedia.org/wiki/Forge_(software)
[local-first]: https://www.inkandswitch.com/local-first/