| + |
---
|
| + |
title: "End of Year Roadmap – 2025"
|
| + |
image: radicle-1.png
|
| + |
layout: blog
|
| + |
---
|
| + |
|
| + |
## The Road Ahead
|
| + |
|
| + |
After the initial 1.0 release, the team was busy polishing certain aspects of
|
| + |
the Radicle tooling and stack. This work resulted in 1.1, 1.2, 1.3, and most
|
| + |
recently 1.4. We can really feel the momentum, and we could not have done it
|
| + |
without the help from contributors also weighing in on the discussion and
|
| + |
submitting patches.
|
| + |
|
| + |
We are close approaching the anniversary of that first release, and as the
|
| + |
project matures, we wanted to take this opportunity to share a roadmap with you.
|
| + |
The aim is to provide some transparency towards what we want to work on, and to
|
| + |
also help contributors focus their attention on ongoing topics.
|
| + |
|
| + |
This is not necessarily a commitment to getting this work done within a certain
|
| + |
time frame. We will always try to aim to work on features and fixes that will
|
| + |
provide the best experience for you and ourselves.
|
| + |
|
| + |
Without further ado, let's put on our cartographer hats on and map out the
|
| + |
direct of the Radicle protocol over the coming months!
|
| + |
|
| + |
## Project Management
|
| + |
|
| + |
First things first, we'll discuss some general management of the project itself.
|
| + |
We want to touch on our release management process and how we will practice
|
| + |
cutting new releases and maintaining patch versions going forward.
|
| + |
|
| + |
### Release Management
|
| + |
|
| + |
The Radicle Protocol team are aiming to improve their release process going
|
| + |
forward. The previous process has got us this far, but we feel like it's time to
|
| + |
take the next step towards more mature workflows.
|
| + |
|
| + |
First, we will quickly discuss the current release process. As a maintainer,
|
| + |
@fintohaps has been using the scripts that are available in `heartwood`:
|
| + |
`build/tag`, `build/build`, `build/upload`, and `build/release`. In order, these
|
| + |
scripts achieve tagging a commit for release, building the binaries – via
|
| + |
`cargo-zigbuild` for cross-compilation, uploading the binaries to our file
|
| + |
server, and finally, marking a binary as the latest. This uses @fintohaps' key
|
| + |
material for signing and verification, and unfortunately, ties the whole process
|
| + |
to them. Before the advent of canonical references, it also meant that it was
|
| + |
tied their particular namespace. The final note here is that we would only
|
| + |
release under minor versions and never attempt to create patch or hotfix
|
| + |
releases.
|
| + |
|
| + |
Proceeding forward, we want to tackle each of these problems to grow towards a
|
| + |
healthier release process. The goal is to have a rotating release maintainer.
|
| + |
For this to happen, the team will share a release signing key. This will be used
|
| + |
to sign the tags for the releases, and can be used by others to verify our
|
| + |
releases. For historical releases, we will ensure to list the older keys that
|
| + |
were used to build them – which will also pave the way for rotating the release
|
| + |
signing key.
|
| + |
|
| + |
We will also begin to release patch and hotfix versions. The process will be
|
| + |
based on a contributors suggestion, and blog post ([How to Do Releases]) –
|
| + |
thanks Matthias. When a Radicle patch provides a fix or improvement that is
|
| + |
considered a hotfix or patch, then the release maintainer will apply to a branch
|
| + |
`releases/1.x`, where `x` is the minor version they are patching. They can then
|
| + |
tag a new patch release, while also creating a `CHANGELOG` entry that is patched
|
| + |
to the `master` branch – describing the changes in the patch release.
|
| + |
|
| + |
Note that these versions only apply to the versions of the binary releases. For
|
| + |
the crates in `heartwood`, we will use `cargo-semverchecks` to detect version
|
| + |
changes and release the crates every 2 weeks. We will start to explore tools
|
| + |
like `cargo-release` and/or `cargo-smart-release` for making the process of
|
| + |
releasing the crates more easier for the team.
|
| + |
|
| + |
If you have any further suggestions, please reach out to us on [Zulip]!
|
| + |
|
| + |
### Yanking `iris` and `rosa`
|
| + |
|
| + |
The Radicle run seed nodes, `rosa.radicle.xyz` and `iris.radicle.xyz`, are set
|
| + |
up to be permissive nodes in the network. This has been a great experience for
|
| + |
users coming to Radicle for the first time. They immediately have nodes that
|
| + |
replicate their projects. Another benefit of this is that we are able to see how
|
| + |
permissive nodes behave and can inspect their logs more easily.
|
| + |
|
| + |
That being said, they are nonetheless a maintenance burden that we, as a team,
|
| + |
do not want to maintain forever.
|
| + |
|
| + |
Going forward, we will be working on reducing how permissive these nodes. Part
|
| + |
of this work relates to [bootstrapping] as well as [policy improvements]. We
|
| + |
will use these nodes to test these features and slowly, but surely, remove them
|
| + |
from the network. Do not worry, we will give ample time and plenty of
|
| + |
announcements on more concrete timelines for when this will be underway.
|
| + |
|
| + |
## Protocol & Node
|
| + |
|
| + |
Now for the juicy parts. Over the past few months, the team has been chipping
|
| + |
away at a few larger topics regarding the protocol and the `radicle-node`. On
|
| + |
top of this, we also met in Helsinki recently and discussed a few potential
|
| + |
topics for the roadmap. Below are the bigger topics that generally touch the
|
| + |
protocol and the node.
|
| + |
|
| + |
### Identity and Multi-Device
|
| + |
|
| + |
These topics are on the mind of every maintainer, contributor, and user of
|
| + |
Radicle. These topics are closely related but can be thought of as two different
|
| + |
beasts. On the one hand, multi-device would mean that any user of Radicle could
|
| + |
work across multiple devices without any issues. This includes using the same
|
| + |
key on two different devices (looking at you YubiKey holders), or associating
|
| + |
different keys to the same person. The latter begins to sound a lot more like
|
| + |
identity, where one person is not identified by a single key, and should be able
|
| + |
to move that identity around with them.
|
| + |
|
| + |
Currently, when someone comes to the Radicle protocol and runs `rad auth` this
|
| + |
generates their signing key. This is used in a myriad of ways:
|
| + |
|
| + |
- The public portion of the key is used as the Node ID
|
| + |
|
| + |
- Which, in turn, is used as part of protocol handshakes
|
| + |
|
| + |
- It also identifies your namespace within a Radicle repository, e.g.
|
| + |
`refs/namespaces/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/refs/heads/main`
|
| + |
|
| + |
- The current DID being used is `did:key` which is derived from the signing key
|
| + |
|
| + |
- The signing key is, naturally, also used for signing data including:
|
| + |
- `rad/sigrefs` – to tell the network that these are the state of your
|
| + |
references
|
| + |
- Changes to collaborative objects
|
| + |
- Announcements, which can be verified by other nodes to ensure that the message
|
| + |
came from you
|
| + |
|
| + |
You may notice that this closely ties a node's identity to a user while also
|
| + |
mixing the responsibility of the user signing data and the node signing data.
|
| + |
|
| + |
As you can see, while these decisions got us up and running quicker, it has come
|
| + |
with consequences. On top of this, we declared a 1.0 for the protocol, and so we
|
| + |
have a duty to attempt to transition towards identity in a backwards-compatible
|
| + |
way.
|
| + |
|
| + |
One of our main tasks will be to slowly provide a separation from the node's key
|
| + |
and the user's key. Some of this work is already underway and is happening with
|
| + |
backwards-compatibility. This may help us towards a story of multi-device, but
|
| + |
we still have some constraints around signing references that blocks us on that
|
| + |
front.
|
| + |
|
| + |
Our other task will be exploring key management systems (KMS) for allowing us to
|
| + |
revoke and rotate keys of a user. The astute reader will notice that `did:key`
|
| + |
does not provide a way to this – its a self describing DID method, and so it
|
| + |
*cannot* provide these functionalities. Currently, we are interested in two key
|
| + |
management systems and exploring their functionality: [Keyhive] and
|
| + |
[BetterSign]. However, the introduction of one of these systems is not as simple
|
| + |
as plugging it in and getting key revocation and rotation. We also need to plan
|
| + |
how those operations play with the current data that we are signing. Some harder
|
| + |
questions need to be answered:
|
| + |
|
| + |
- How do we continue to verify historical data?
|
| + |
- How do we handle revoked data that has been signed by a compromised key?
|
| + |
- How do we evolve the Git namespaces when a new key is introduced?
|
| + |
- Can we do this in a backwards-compatible fashion?
|
| + |
|
| + |
Finally, we want to provide a consistent identity for a person (or more
|
| + |
generally an agent – no, not AI) that acts within the Radicle network. For this,
|
| + |
we have started to draft a [RIP][Agent Repository RIP] that describes a way for
|
| + |
us to represent an identity that could be communicated using the Radicle
|
| + |
protocol. This draft needs to be further developed and tested with an
|
| + |
implementation in the `heartwood` repository.
|
| + |
|
| + |
Admittedly, due to the size of these problems, the consequences of making these
|
| + |
changes, and its lasting implications on the protocol we have moved a bit slower
|
| + |
on this front. It has, however, never been forgotten and we will continue to
|
| + |
push towards an implementation for identity and multi-device.
|
| + |
|
| + |
### Migration of network I/O in `radicle-node` to `mio`
|
| + |
|
| + |
[Migration to mio]: #Migration-of-network-IO-in-radicle-node-to-mio
|
| + |
|
| + |
The crates [`netservices`], [`io-reactor`], and [`popol`] have served us well to
|
| + |
implement `radicle-node`. However, they are not ideal dependencies for ensuring
|
| + |
long-term health of our network I/O layer:
|
| + |
- [`popol`] is only intended to support Unix-like platforms, and we are looking
|
| + |
to support other platforms, like [Windows].
|
| + |
|
| + |
- Even though `io-reactor` defines the trait [`reactor::poller:Poll`] to
|
| + |
potentially support multiple I/O polling mechanisms, there only is one single
|
| + |
implementation for wrapping `popol`. Issues for other polling crates are open
|
| + |
since 2023 without tangible progress: [#10 for `mio`], [#9 for `polling`], [#8
|
| + |
for `epoll`]. This suggests that it is not a high priority for the maintainers
|
| + |
to integrate with other polling abstractions (which might offer better
|
| + |
cross-platform compatibility).
|
| + |
|
| + |
- The trait [`reactor::poller:Poll`] can only be implemented for file
|
| + |
descriptors which also implement [`std::os::fd::raw::AsRawFd`] and this trait
|
| + |
is only implemented on Unix-like platforms and WASI. We believe that this is
|
| + |
leaked from `popol` as the only known implementation of the trait wraps it.
|
| + |
|
| + |
- We would like to benefit from network effects, i.e. from other people
|
| + |
maintaining crates that depend on `io-reactor` to implement support for other
|
| + |
pollers. However, [according to crates.io, the only dependent is
|
| + |
`radicle-node`][io-reactor-dependents] (via `netservices`). Contrary to that,
|
| + |
at the time of writing, [`mio` has 494 dependents according to
|
| + |
crates.io][mio-dependents], and, notably, [`tokio`, which has 30628 dependents
|
| + |
on crates.io, is dependent on `mio`][tokio-dependents]. We therefore think
|
| + |
that even if `mio` is obsoleted, e.g. by [`a10`] (which is based on
|
| + |
[`io_uring`] on Linux and could potentially build on top of [I/O rings on
|
| + |
Windows]) the people behind a large network of dependent projects will come up
|
| + |
with new ideas and solutions, that we would then benefit from.
|
| + |
|
| + |
- One downside of `mio` is that it forces the use of [`mio::Token`] to identify
|
| + |
sources (while a type that is `Eq + Clone` might be enough), and that it
|
| + |
forces the use of the types in [`mio::net`] for sockets, which need to be
|
| + |
converted to/from [`std::net`] if required. These distinctions are also [noted
|
| + |
by cloudhead]. We are willing to buy in that far to `mio` to leverage the
|
| + |
benefits of a well-tested and cross-platform network I/O layer.
|
| + |
|
| + |
A proof-of-concept is submitted as [patch `5ea90b97`].
|
| + |
|
| + |
### Windows Compatibility
|
| + |
|
| + |
[Windows]: Windows Compatibility
|
| + |
|
| + |
If we truly want Radicle to succeed, it is necessary that we attempt to provide
|
| + |
the technology to as many people as we can. This should include Windows users.
|
| + |
|
| + |
A pure Windows build of the `heartwood` repository has not been a number one
|
| + |
priority for the team since we started. The fact is that none of the team used
|
| + |
Windows, with the majority of us on a flavour of Linux and a few MacOS users.
|
| + |
That did not stop some interested users on Windows coming along and asking
|
| + |
questions!
|
| + |
|
| + |
More recently, a team member who has access to a Windows machine has started to
|
| + |
slowly get some parts of the system working on Windows[^1][^2][^3]. This has
|
| + |
allowed some interaction with Radicle via the `rad` CLI, and started paving the
|
| + |
way to getting the `radicle-node` to also build. To get to that, we need to make
|
| + |
some changes to not rely on Unix specific utilities and take control of the
|
| + |
underlying networking libraries and house changes to them within `heartwood` –
|
| + |
with a draft patch already in place (See [Migration to mio]).
|
| + |
|
| + |
We also want to ensure that once we have Windows compatibility in place, that we
|
| + |
do not easily lose it. We will move towards testing more strictly in CI and have
|
| + |
a target that checks the builds on Windows. This will place Windows as a "second
|
| + |
tier" platform within our ecosystem – meaning we will try support it, but it
|
| + |
will not always be our first priority.
|
| + |
|
| + |
### Road to a Sans-I/O Protocol
|
| + |
|
| + |
While diving deeper into the `radicle-node` protocol, we realised that we were
|
| + |
finding it hard to understand and modify the innards of the protocol code. The
|
| + |
logic of what happens in the protocol was tied to the I/O of calling to the
|
| + |
network, modifying sqlite databases, etc. At that point, we decided that it was
|
| + |
time to explore [Sans-I/O].
|
| + |
|
| + |
This effort has already begun. The first step was moving the majority of the
|
| + |
code from `radicle-node` into a new `radicle-protocol` crate. This kept the
|
| + |
majority of the code as-is, but removed any dependencies on any crates that were
|
| + |
required to perform I/O. These were plugged in via `radicle-node`. This was only
|
| + |
the beginning.
|
| + |
|
| + |
To better understand these techniques, we have also made efforts to separate
|
| + |
"business logic" away from I/O in smaller components of our code base. This has
|
| + |
been a great process and has resulted in code that is easier to reason about
|
| + |
*and* easier to test. This may be obvious to most people, but sometimes as
|
| + |
programmers, we cut corners to get to a result faster – and one of those corners
|
| + |
is mixing our business logic with I/O.
|
| + |
|
| + |
We have already started working towards a sans-I/O [implementation of the
|
| + |
protocol][Sans-I/O Patch]. We have been dissecting the code that is in
|
| + |
`radicle-protocol`, and finding components that have a single responsibility.
|
| + |
These components are being defined using an event and command architecture.
|
| + |
These components will then be composed to have an architecture that can be
|
| + |
driven by commands and will output events – which can then be logged, made into
|
| + |
metrics, notify the user, etc.
|
| + |
|
| + |
Once this has been sketched and tested, we plan on having a version of
|
| + |
`radicle-node` that uses this version of the protocol and ensure that it has
|
| + |
compatibility with the previous version.
|
| + |
|
| + |
From this point on, we will aim to explore how this helps us improve the
|
| + |
protocol. We will explore the possibility of new protocol messages, and better
|
| + |
error handling for Git fetches. As well as this, we want to explore different
|
| + |
networking libraries such as [`iroh`] and [`libp2p`].
|
| + |
|
| + |
### Policy Improvements
|
| + |
|
| + |
[policy improvements]: #policy-improvements
|
| + |
|
| + |
The team was thinking about ways to improve node storage management and
|
| + |
moderation. One of the team noted a mode of behaviour that could be implemented
|
| + |
that was dubbed quarantining, at the time. The basic idea is that a node could
|
| + |
say it wants to fetch a repository but not advertise it as part of its own
|
| + |
inventory. Put another way, the repository is in storage, but it is not being
|
| + |
announced to the network.
|
| + |
|
| + |
So, what is the value of this mode of operation? Once this repository has been
|
| + |
fetched, it means that it can be inspected to evaluate whether the node operator
|
| + |
wishes to announce it as part of the node's inventory. If the repository is
|
| + |
deemed worthy, then it can be promoted to be seeding, and if not, then it can be
|
| + |
blocked.
|
| + |
|
| + |
Node operators can begin to ask questions like:
|
| + |
- How big is this repository?
|
| + |
- Can I detect illicit content in this repository?
|
| + |
- Are the delegates part of my follow list?
|
| + |
- Is this a Rust project?
|
| + |
- etc.
|
| + |
|
| + |
Essentially, this provides enough power to the operator, and the general
|
| + |
ecosystem as a whole, to begin experimenting with their own kinds of moderation
|
| + |
and node management.
|
| + |
|
| + |
The idea did not stop there. As we tugged on this concept more, we started to
|
| + |
compare it more to the existing behaviour. The existing modes are "seed" and
|
| + |
"block". The former says that the node will fetch and announce the repository,
|
| + |
while the latter says it will ignore it completely. We were now proposing a mode
|
| + |
that is only fetching, and we began to wonder about a mode that would only be
|
| + |
announce. After considering these different modes, potential use cases, and
|
| + |
playing around with wording, we came to the conclusion that this concept seems
|
| + |
to lie close to a [publish-subscribe] method. The repository is a topic,
|
| + |
fetching is subscribing, announcing is publishing, and we have the option to
|
| + |
block the topic.
|
| + |
|
| + |
After this brief foray into thought, we have decided to formalise a RIP for
|
| + |
improving policies and explore the implementation in `heartwood`. The change to
|
| + |
the node behaviour seems to be straight-forward, however, the CLI tooling and
|
| + |
terminology seems to be the more challenging portion of this set of changes.
|
| + |
|
| + |
### Reaping Repositories
|
| + |
|
| + |
It has been a common occurrence that someone decides to try out Radicle, and
|
| + |
they test it out on a repository – with an apt name, such as
|
| + |
`radicle-test`[^4][^5][^6]. The next question on their mind is, "How do I
|
| + |
delete this repository?" They don't see an immediate answer in the set of `rad`
|
| + |
commands, and they ask the same question in our [Zulip]. Unfortunately, up
|
| + |
until this point, there has been no mechanism for deleting a repository.
|
| + |
|
| + |
Initially, we punted on it because in a decentralized network, you cannot go
|
| + |
around to each machine and delete content – that would be censorship
|
| + |
susceptible[^7]. After some thought, we decided that we could implement a
|
| + |
mechanism where one could *ask* for their repository to be deleted.
|
| + |
|
| + |
The basis of this feature is to define a payload extension for the identity
|
| + |
document, that could be added to set an expiry date for the repository. Other
|
| + |
nodes and node operators can then decide, based on the expiry, to reap the
|
| + |
repository from their storage, and block it so that they would not replicate it
|
| + |
again. Essentially, if you wanted to delete the repository, then you would set
|
| + |
the expiry to the current date-time and announce that to the network.
|
| + |
|
| + |
The aim for this feature is to provide this basic mechanism and supplement it
|
| + |
with tooling through the `rad` CLI so that a node operator can easily detect
|
| + |
expired repositories, and a user can ensure that their repository continues to
|
| + |
live or die in the Radicle network.
|
| + |
|
| + |
### Bootstrapping
|
| + |
|
| + |
[bootstrapping]: #bootstrapping
|
| + |
|
| + |
To get things up and running, the Radicle team put together seed nodes – now
|
| + |
called `rosa.radicle.xyz` and `iris.radicle.xyz` – that act as bootstrap nodes
|
| + |
to the network. This means that these nodes will relay gossip for new nodes that
|
| + |
join the network. When someone sets up a new node in the Radicle network, their
|
| + |
Node ID and some other useful information well be gossiped to other nodes via
|
| + |
the seeds.
|
| + |
|
| + |
We and other contributors feel that these nodes should not be necessarily
|
| + |
defined as part of the `heartwood` repository. The bootstrap process should be
|
| + |
configured by the user, where the Radicle team can provide help and resources
|
| + |
for picking nodes. This can be a similar process to how Arch Linux users pick
|
| + |
their mirrors for retrieving packages from. This kind of work has already been
|
| + |
[kicked off][Remove Bootstrap Nodes], but needs some more input to progress it
|
| + |
further.
|
| + |
|
| + |
The aim of this is to encourage more decentralization of the network, allowing
|
| + |
operators to act as bootstrap nodes in the future. The team would slowly wind
|
| + |
down the use of `rosa` and `iris` to reduce the maintenance burden of operating
|
| + |
seeds as well as developing the protocol. The road map for this process would be
|
| + |
to remove them as predefined nodes in `heartwood`, and then slowly decommission
|
| + |
them.
|
| + |
|
| + |
### Compatibility with Git Worktrees
|
| + |
|
| + |
The current setup of Radicle defines a directory where it stores repositories.
|
| + |
These repositories essentially contain the usual references that you interact
|
| + |
with, each under [namespaces][Git Namespaces] of each node, as well as special
|
| + |
references such as `rad/sigrefs` and collaborative objects, e.g.
|
| + |
`xyz.radicle.patch`, `xyz.radicle.issue`. This acts as the user's forge, where
|
| + |
they can push and pull updates – using `git push` and `git fetch`, and interact
|
| + |
with collaborative objects through the the `rad` CLI. It's important to note,
|
| + |
however, that they do this through a working copy of the repository – a non-bare
|
| + |
repository which is a copy of the repository in storage.
|
| + |
|
| + |
There is a slight issue with this – it means you are duplicating the repository
|
| + |
on your disk, and for very large repositories this could mean taking up to the
|
| + |
range of 10's of gigabytes of disk space. So, we asked ourselves, is there a way
|
| + |
to unify these two repositories?
|
| + |
|
| + |
The answer, we believe, is [Git Worktrees]. The idea is that the Radicle storage
|
| + |
would also be your working copy. When you want to make changes to your
|
| + |
namespace, then you would create a new worktree based on a reference that you
|
| + |
want to work on top of, for example, the default branch of the repository.
|
| + |
|
| + |
To get to this point, we will need to improve certain aspects around reference
|
| + |
handling, primarily with canonical references, and also teach our tooling to
|
| + |
work better with bare Git repositories.
|
| + |
|
| + |
This will not only improve the storage space situation but may also feel more
|
| + |
natural to some developers who prefer working with worktrees.
|
| + |
|
| + |
## Developer Experience
|
| + |
|
| + |
### Migrating Radicle CLI to `clap`
|
| + |
|
| + |
If you have been looking up `rad` options all the time, `clap` your hands! We
|
| + |
will start migrating our `rad` CLI command-line parsing over to the [`clap`]
|
| + |
crate.
|
| + |
|
| + |
Up until this point, we have been using [`lexopt`] to parse command-line
|
| + |
arguments. The choice here was to have a small dependency that was flexible for
|
| + |
defining our own help messages. At the time, `clap` was going through its major
|
| + |
rewrite and was moving towards the `v3.0.0` release.
|
| + |
|
| + |
While minimising dependency footprint is a useful endeavour, the team and
|
| + |
contributors were feeling the pain of maintaining and hand writing out parsing
|
| + |
logic for any and all of the CLI commands, using `lexopt`. Last year, we did a
|
| + |
spike on exploring `clap` to see if it could be useful for adding completions
|
| + |
and providing dynamic hints, such as patch and issue identifier completions.
|
| + |
This gave us an idea of how using `clap` would work, but there was still some
|
| + |
need for additional upstream changes back then, and ultimately the experiment
|
| + |
was dropped for more pressing matters.
|
| + |
|
| + |
A while later, this was revisited again, and the main part of the exploration
|
| + |
was checking if we could keep somewhat compatible help messages for the
|
| + |
commands. It was found that with some boilerplate, we likely could. However, yet
|
| + |
again, our attentions were diverted elsewhere.
|
| + |
|
| + |
Now, with enough interest in the change, we have picked the effort back up to
|
| + |
bring this change over the finish line. We hope to leverage all that `clap`
|
| + |
brings with it: automatic argument parsing, completion tooling, a rich library
|
| + |
experience, and an ever evolving ecosystem of tools around `clap` itself.
|
| + |
|
| + |
### Code Review Research
|
| + |
|
| + |
[Code Review Research][#code-review-research]
|
| + |
|
| + |
If you have been using Radicle for any amount of time, you will have likely used
|
| + |
patches that are defined as part of the `rad` CLI, and the `git-remote-rad` [Git
|
| + |
remote helper]. This is and has been the primary way of exchanging code changes
|
| + |
via Radicle. This has bought us a lot, allowing us to propose new changes and
|
| + |
track the work that is going on through these patch contributions.
|
| + |
|
| + |
If you have been part of the Radicle [Zulip], you will have also noticed that
|
| + |
maintainers of the `heartwood` repository tend to have discussions in the
|
| + |
[#Patches] channel. This is where we do the majority of our review. We combine
|
| + |
these discussions with creating `REVIEW` commits and pushing these as a new
|
| + |
patch revision, for the original author to accept, modify, or drop.
|
| + |
|
| + |
On top of this, those who have dug around in the `rad patch` command will have
|
| + |
noticed that `rad patch review --patch` and `rad patch review --hunk` seemingly
|
| + |
have a flow for reviewing code. These operations, unfortunately, were never
|
| + |
wired up fully and are built on pieces of code that do not pan out with our
|
| + |
underlying libraries. Going forward, we intend to remove these options. You may
|
| + |
ask if this breaks backwards-compatibility, but we are of the opinion that if it
|
| + |
didn't work in the first place, then there is nothing to be compatible with!
|
| + |
However, there are still ways to submit patch reviews, through [Radicle
|
| + |
Desktop], a future release of [Radicle TUI], and `rad cob action` (this requires
|
| + |
a bit more documentation for proper use).
|
| + |
|
| + |
Where does that leave us for code review? We believe that this is a more complex
|
| + |
and multifaceted problem, that requires a lot more thought and design. Whole
|
| + |
teams have gone into building tools that perform code review, e.g. Jane Street's
|
| + |
Iron and Google's Gerrit. Now take these problems and also add people who want
|
| + |
use their own diff tools, crafted diff settings (e.g. diff algorithm), and still
|
| + |
make sure it works in an environment of decentralized collaboration. The
|
| + |
landscape of tooling is also changing, where we see more and more users flocking
|
| + |
towards [Jujutsu-VCS], where even some of our team are finding it useful for
|
| + |
[their day-to-day][Jujutsu with Radicle]. The usage of `jj` seems to have even
|
| + |
had a ripple effect of introducing change IDs into [Git itself][change-id commit
|
| + |
footer]!
|
| + |
|
| + |
We are happy to start this research and start dropping down our ideas – but
|
| + |
we're a small team. This is somewhere where the whole community could really
|
| + |
benefit by getting involved, researching these tools, and helping us build
|
| + |
something that could be great. Let's collaborate to improve collaboration! 🌱
|
| + |
|
| + |
### COB API Documentation
|
| + |
|
| + |
In the Radicle protocol, Collaborative Objects (COBs) play an important role in
|
| + |
supplementing Git with social artifacts such as issues, patches and discussions,
|
| + |
which are not inherently supported by Git. It includes three predefined
|
| + |
collaborative object types to support code collaboration: *Issues*, *Patches*,
|
| + |
and *Identities*.
|
| + |
|
| + |
These COBs are primarily interacted with through their `rad` sub-commands,
|
| + |
`issue`, `patch`, and `id` respectively. However, the full set of interactions
|
| + |
is not covered by these commands yet. For example, there is no way to add a
|
| + |
review comment using the `rad patch` command (see [Code Review Research]). That
|
| + |
does not mean that there is *no way* of doing this using the `rad` CLI. There is
|
| + |
a set of low-level, plumbing commands under `rad cob` that allow you to add COB
|
| + |
actions for updating an object – note that for the `Identity` COB, these updates
|
| + |
are not permitted, since we want strict validation of what can happen here. With
|
| + |
this in mind, we want to better document these commands and show how these
|
| + |
actions can be used for modifying the objects, which means outside tooling can
|
| + |
programmatically modify the objects by making CLI calls.
|
| + |
|
| + |
On top of this, we want to encourage more experimentation with COBs that can be
|
| + |
defined by other contributors outside of the team, outside of the `heartwood`
|
| + |
repository. We will supplement the above documentation with further tutorials on
|
| + |
how to define your own COBs and create your own workflows.
|
| + |
|
| + |
We plan to have all this information presented in a COB Guide on
|
| + |
[radicle.xyz/guides][Guides], and we look forward to hearing about all the
|
| + |
amazing COBs people will dream up!
|
| + |
|
| + |
### `rad` URI
|
| + |
|
| + |
A feature that we are missing in the Radicle ecosystem is being able to link to
|
| + |
resources easily. For example, there is no way to cross-link a patch to an issue
|
| + |
saying that, when merged, the issue is solved – something that GitHub users have
|
| + |
grown fond of.
|
| + |
|
| + |
Lorenz made an effort to kick-off discussion around this topic in a [RIP][Early
|
| + |
URI Proposal] that linked to a notepad of rough notes on the topic. Now, thanks
|
| + |
to the effort of Richard Levitte (`levitte`), the topic has been revived in
|
| + |
[another RIP proposal][`rad URI RIP`].
|
| + |
|
| + |
The goal here is to have a full specification of what the URI grammar looks like
|
| + |
for identifying resources in Radicle, such as repositories, Git objects, and
|
| + |
collaborative objects. Applications can then use these URIs for linking to these
|
| + |
resources within their application, users can have registered handlers for
|
| + |
taking them to their preferred Radicle application, and we can begin to support
|
| + |
automated workflows such as the one mentioned above with patches and issues.
|
| + |
With a mature scheme, we can also register it with [IANA][RFC 4395 – URI Scheme
|
| + |
Registration].
|
| + |
|
| + |
<!-- Zulip -->
|
| + |
[Zulip]: https://radicle.zulipchat.com
|
| + |
|
| + |
<!-- Release Management -->
|
| + |
[How To Do Releases]: https://beyermatthias.de/how-to-do-releases
|
| + |
|
| + |
<!-- Identity and Multi-Device -->
|
| + |
[Keyhive]: https://www.inkandswitch.com/keyhive/notebook/
|
| + |
[BetterSign]: https://github.com/cryptidtech/bs
|
| + |
[Agent Repository RIP]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/27fea5d31ad98a49b2b5b7520d196620c3ed2b92
|
| + |
|
| + |
<!-- Migration of network I/O in `radicle-node` to `mio` -->
|
| + |
[`netservices`]: https://crates.io/crates/netservices
|
| + |
[`io-reactor`]: https://crates.io/crates/io-reactor
|
| + |
[`popol`]: https://crates.io/crates/popol
|
| + |
[`reactor::poller:Poll`]: https://docs.rs/io-reactor/0.5.2/reactor/poller/trait.Poll.html
|
| + |
[#10 for `mio`]: https://github.com/rust-amplify/io-reactor/issues/10
|
| + |
[#9 for `polling`]: https://github.com/rust-amplify/io-reactor/issues/9
|
| + |
[#8 for `epoll`]: https://github.com/rust-amplify/io-reactor/issues/8
|
| + |
[`reactor::poller:Poll`]: https://docs.rs/io-reactor/0.5.2/reactor/poller/trait.Poll.html
|
| + |
[`std::os::fd::raw::AsRawFd`]: https://doc.rust-lang.org/nightly/std/os/fd/raw/trait.AsRawFd.html
|
| + |
[io-reactor-dependents]: https://crates.io/crates/io-reactor/reverse_dependencies
|
| + |
[mio-dependents]: https://crates.io/crates/mio/reverse_dependencies
|
| + |
[tokio-dependents]: https://crates.io/crates/tokio/reverse_dependencies
|
| + |
[`a10`]: https://crates.io/crates/a10
|
| + |
[`io_uring`]: https://en.wikipedia.org/wiki/Io_uring
|
| + |
[I/O rings on Windows]: https://learn.microsoft.com/en-us/windows/win32/api/ioringapi/
|
| + |
[`mio::Token`]: https://docs.rs/mio/1.0.4/mio/struct.Token.html
|
| + |
[`mio::net`]: https://docs.rs/mio/1.0.4/mio/net/index.html
|
| + |
[`std::net`]: https://doc.rust-lang.org/stable/std/net/index.html
|
| + |
[noted by cloudhead]: https://cloudhead.io/popol/
|
| + |
[patch `5ea90b97`]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/5ea90b9757059522e80301bbd9b1458a39a71f7e
|
| + |
|
| + |
<!-- Windows Compatibility -->
|
| + |
[^1]: [radicle-cli: Build on Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/af3292c47ec93d906ccda8d9382f711c2201e678)
|
| + |
[^2]: [node: Use winpipe for control socket on Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/5109cda98885b00c1d4f7165013e4d66f9b7512f)
|
| + |
[^3]: [radicle/profile: Control socket path for Windows](https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/c7498dcdee66fbca673c7d6b85dfc18555fbd988)
|
| + |
|
| + |
<!-- Road to Sans-I/O Protocol -->
|
| + |
[Sans-I/O]: https://sans-io.readthedocs.io/
|
| + |
[Sans-I/O
|
| + |
Patch](https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/511ad5ad569fea9124a9ad4738431e42b5075675)
|
| + |
[iroh]: https://www.iroh.computer/
|
| + |
[libp2p]: https://libp2p.io/
|
| + |
|
| + |
<!-- Policy Improvements -->
|
| + |
[publish-subscribe]: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
|
| + |
|
| + |
<!-- Reaping Repositories -->
|
| + |
[^4]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az23FUbgvSZMtshnoYuxmvaHfgMsCe
|
| + |
[^5]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az2H5Cae9kLahf57MbYoipimZzF2VU
|
| + |
[^6]: https://app.radicle.xyz/nodes/seed.radicle.garden/rad%3Az2KGZouSGAtbVcK4wkpWJP3MXSK3h
|
| + |
[^7]: One of the tenets of the Radicle protocol is to offer censorship resistance.
|
| + |
|
| + |
<!-- Bootstrapping -->
|
| + |
[Remove Bootstrap Nodes]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patches/3219ef871dd44c7ef51693f4aeba4c2c5c0c5c7b
|
| + |
|
| + |
<!-- Compatibility with Git Worktrees -->
|
| + |
[Git Namespaces]: https://git-scm.com/docs/gitnamespaces
|
| + |
[Git Worktrees]: https://git-scm.com/docs/git-worktree
|
| + |
|
| + |
<!-- Migrating Radicle CLI to clap -->
|
| + |
[clap]: https://crates.io/crates/clap
|
| + |
[lexopt]: https://crates.io/crates/lexopt
|
| + |
|
| + |
<!-- Code Review Research -->
|
| + |
[Git remote helper]: TODO
|
| + |
[#Patches]: https://radicle.zulipchat.com/#narrow/channel/383670-Patches
|
| + |
[Radicle Desktop]: https://desktop.radicle.xyz/
|
| + |
[Radicle TUI]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z39mP9rQAaGmERfUMPULfPUi473tY
|
| + |
[Jujutsu-VCS]: https://jj-vcs.github.io/jj/latest/
|
| + |
[Jujutsu with Radicle]: https://radicle.xyz/2025/08/14/jujutsu-with-radicle
|
| + |
[change-id commit footer](https://lore.kernel.org/git/CAESOdVAspxUJKGAA58i0tvks4ZOfoGf1Aa5gPr0FXzdcywqUUw@mail.gmail.com/)
|
| + |
|
| + |
<!-- COB API Documentation -->
|
| + |
[Guides]: https://radicle.xyz/guides
|
| + |
|
| + |
<!-- rad URI -->
|
| + |
[Early URI Proposal]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/19ba16634fbde97156255ed97069d0aa3ab2bf12
|
| + |
[`rad` URI RIP]: https://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z3trNYnLWS11cJWC6BbxDs5niGo82/patches/2e2061857d703b8467648ff2b77efd61c72ca583
|
| + |
[RFC 4395 – URI Scheme Registration]: https://www.rfc-editor.org/rfc/rfc4395.html#section-5
|