research/radicle-decentralized-git/analysis.md

71 lines
5.5 KiB
Markdown

# Analysis — Radicle: Decentralized Git Network & Forge
> Part of [[radicle-decentralized-git/index|Radicle — Decentralized Git Network & Forge]]
## 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