research/radicle-decentralized-git/analysis.md

5.5 KiB

Analysis — Radicle: Decentralized Git Network & Forge

Part of radicle-decentralized-git/index

How the protocol works (deep dive)

1. Nodes and identities

  • Every participant runs a node — a background daemon (radicle-node) that is both client and server.
  • Identity = Ed25519 public key, encoded as a W3C DID (did:key:z6Mk...). Generated offline; no email, no registry, no permission.
  • A node seeds repositories it is interested in; the seeding policy defines which repos it keeps and offers to the network.
  • Always-on seed nodes (public or community) increase availability. Bootstrap via two well-known nodes (iris.radicle.network, rosa.radicle.network) when the address book is empty.

2. Gossip protocol (discovery metadata)

Three signed, timestamped message types relayed between peers:

  • Node announcements — broadcast Node ID + reachable addresses (peer discovery)
  • Inventory announcements — broadcast which repositories a node hosts (routing table: repo → hosts)
  • Refs announcements — broadcast repository updates, relayed only to interested nodes (rid + updated signed refs)
  • Dedup (drop seen messages) prevents infinite propagation; messages are replayed to newly-joined nodes.
  • Every announcement carries the originating Node ID, a cryptographic signature, and a timestamp → peers verify before relaying.

3. Transport

  • Noise XK handshake (same pattern as Lightning Network): nodes must know the peer's static key (their Node ID) before connecting — learned via gossip.
  • Full forward secrecy after handshake. Tor addresses supported for IP anonymity.

4. Replication via Git

  • Actual repository data transfers over the standard Git pack protocol (fetch/negotiation).
  • Framing/multiplexing lets gossip + git fetch coexist over one physical connection — efficient, avoids NAT issues.

5. Self-certifying repositories

  • Repo identity document (canonical JSON) under refs/rad/id: delegates (DIDs), signature threshold, name/description/defaultBranch.
  • RID = rad: + base58btc(SHA-1 of the initial identity document) — stable even as the doc evolves.
  • Every ref change is signed into refs/rad/sigrefs (a Git blob listing refs + OIDs). Anyone can verify the full history from the RID + clone — no trusted third party (TUF-inspired).
  • Canonical branch: the default branch's authoritative state = the commit that N-of-M delegates have pushed (threshold from identity doc). Not a server rule — a cryptographic quorum.
  • Private repos: visibility: private + allow list of DIDs → selective replication (not encryption at rest).

6. Collaborative Objects (COBs)

  • Social artifacts (issues, patches, reviews) are Git commit DAGs under refs/cobs/<type>/<id>.
  • Convergent like CRDTs: union of histories + topological (causal) reduction + deterministic merge. Concurrent edits converge without a server.
  • Three built-in types: issues (xyz.radicle.issue), patches (xyz.radicle.patch), identities (xyz.radicle.id). New types = new namespaces — fully programmable.

7. Storage layout

  • All repos are bare Git repos under <storage>/<rid>/, with per-peer Git namespaces (refs/namespaces/<nid>/...) sharing one object database.
  • Users interact with a working copy + the node's stored copy via git-remote-rad over rad://<rid>/<nid> URLs.
  • Offline work is first-class: pushes/fetches happen whenever the node is connected.

Forgejo vs Radicle — should we run both?

Complementary roles (not replacements)

  • Forgejo (current): mature forge experience — web UI, issues/PRs, CI (Forgejo Actions), mirroring, private repos, admin control, Forgejo API for our agents.
  • Radicle: decentralized network presence — no server to maintain, censorship-resistant, cross-instance collaboration, COB programmability, jj-friendly.

What we gain from a Radicle node

  1. Sovereignty redundancy: public repos remain reachable even if greencloud-vps is down (other seeds)
  2. No fragmentation: external collaborators without a Forgejo account can still clone/contribute over Radicle
  3. Agent-native collaboration: COBs as programmable, signed objects — matches our durable-agent-runtime direction (agents as first-class participants)
  4. Low maintenance: a seed node is a lightweight daemon; no web UI/CI/backup surface of a forge

What we give up / risks

  1. Discovery: no GitHub-scale search; network effects still small
  2. Social layer maturity: issues/patches UX younger than Forgejo's
  3. Availability: our own repos are only reachable while some seed is online — so we'd want our seed always-on (hermes-vm or greencloud-vps)
  4. Another protocol surface: new key material, new daemon, new storage dir to back up

Verdict

Worth a trial, not a migration. Run a Radicle seed node on hermes-vm (or greencloud-vps) beside Forgejo, mirror public repos for presence, keep Forgejo as the primary forge. Decision to invest deeper (dedicated seed service in clan-private, COB-based workflows, moving a project's issue tracking) only after an external collaborator actually uses Radicle.

Notes for our stack

  • Radicle CLI + daemon installable via Nix; seed node needs a stable identity key (back it up!)
  • jj interop works via rad:// remotes
  • Keep private repos on Forgejo (Radicle private = selective replication, not encryption; Forgejo private + access control is simpler for our use)
  • Radicle Garden is the hosted option if we don't want to run our own seed — but self-hosting matches our sovereignty principle