rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood91eb6fc078727337449c203b8cf54aba4f40d816
{
"request": "trigger",
"version": 1,
"event_type": "push",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"pusher": {
"id": "did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz",
"alias": "lorenz"
},
"before": "91eb6fc078727337449c203b8cf54aba4f40d816",
"after": "91eb6fc078727337449c203b8cf54aba4f40d816",
"branch": "master",
"commits": [
"91eb6fc078727337449c203b8cf54aba4f40d816",
"36d5a4c8b057830ed9556d6330e271e75d015091",
"73f9a350331f6c6269f7f60e1e94612c948fb423",
"589925e3a3d792b321661a2e3f33b1f38be15063",
"8b1d475170accf4288cfe39286b9c959618cf736"
]
}
{
"response": "triggered",
"run_id": {
"id": "75c5a90a-21d4-46f7-8c85-b442e986c574"
},
"info_url": "https://cci.rad.levitte.org//75c5a90a-21d4-46f7-8c85-b442e986c574.html"
}
Started at: 2026-01-26 18:56:48.368240+01:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW added
✓ Remote-tracking branch cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW/master created for z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz added
✓ Remote-tracking branch erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz/master created for z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/75c5a90a-21d4-46f7-8c85-b442e986c574/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 136 issues · 16 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 91eb6fc078727337449c203b8cf54aba4f40d816
HEAD is now at 91eb6fc0 protocol: ensure `connect` supports connecting address
Exit code: 0
$ git show 91eb6fc078727337449c203b8cf54aba4f40d816
commit 91eb6fc078727337449c203b8cf54aba4f40d816
Author: Fintan Halpenny <fintan.halpenny@gmail.com>
Date: Mon Jan 26 14:40:32 2026 +0000
protocol: ensure `connect` supports connecting address
Be more defensive by preventing a node, that is not configured for
Tor, to not connect to `.onion` addresses via the `Service::connect`
method.
This means that an `Outbox::connect` should not be produced, and the
address table should not insert an entry.
diff --git a/crates/radicle-protocol/src/service.rs b/crates/radicle-protocol/src/service.rs
index 405dd223..b36c5e95 100644
--- a/crates/radicle-protocol/src/service.rs
+++ b/crates/radicle-protocol/src/service.rs
@@ -221,6 +221,8 @@ pub enum ConnectError {
SelfConnection,
#[error("outbound connection limit reached when attempting {nid} ({addr})")]
LimitReached { nid: NodeId, addr: Address },
+ #[error("attempted connection to {nid}, via {addr} but addresses of this kind are not supported")]
+ UnsupportedAddress { nid: NodeId, addr: Address },
}
/// A store for all node data.
@@ -2265,6 +2267,9 @@ where
if nid == self.node_id() {
return Err(ConnectError::SelfConnection);
}
+ if !self.is_supported_address(&addr) {
+ return Err(ConnectError::UnsupportedAddress { nid, addr });
+ }
if self.sessions.contains_key(&nid) {
return Err(ConnectError::SessionExists { nid });
}
@@ -2503,7 +2508,7 @@ where
.filter(|entry| !self.sessions.contains_key(&entry.node))
.filter(|entry| !self.config.external_addresses.contains(&entry.address.addr))
.filter(|entry| &entry.node != self.nid())
- .filter(|entry| !entry.address.addr.is_onion() || self.config.onion.is_some())
+ .filter(|entry| self.is_supported_address(&entry.address.addr))
.fold(HashMap::new(), |mut acc, entry| {
acc.entry(entry.node)
.and_modify(|e: &mut Peer| e.addresses.push(entry.address.clone()))
@@ -2641,11 +2646,7 @@ where
})
.map(|ka| (peer.nid, ka))
})
- .filter(|(_, ka)| match AddressType::from(&ka.addr) {
- // Only consider onion addresses if configured.
- AddressType::Onion => self.config.onion.is_some(),
- AddressType::Dns | AddressType::Ipv4 | AddressType::Ipv6 => true,
- });
+ .filter(|(_, ka)| self.is_supported_address(&ka.addr));
// Peers we are going to attempt connections to.
let connect = available.take(wanted).collect::<Vec<_>>();
@@ -2689,6 +2690,24 @@ where
}
}
}
+
+ /// Checks if the given [`Address`] is supported for connecting to.
+ ///
+ /// # IPv4/IPv6/DNS
+ ///
+ /// Always returns `true`.
+ ///
+ /// # Tor
+ ///
+ /// If the [`Address`] is an `.onion` address and the service supports onion
+ /// routing then this will return `true`.
+ fn is_supported_address(&self, address: &Address) -> bool {
+ match AddressType::from(address) {
+ // Only consider onion addresses if configured.
+ AddressType::Onion => self.config.onion.is_some(),
+ AddressType::Dns | AddressType::Ipv4 | AddressType::Ipv6 => true,
+ }
+ }
}
/// Gives read access to the service state.
Exit code: 0
shell: 'export RUSTDOCFLAGS=''-D warnings'' cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny warnings cargo build --all-targets --workspace cargo doc --workspace --no-deps --all-features cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name 75c5a90a-21d4-46f7-8c85-b442e986c574 -v /opt/radcis/ci.rad.levitte.org/cci/state/75c5a90a-21d4-46f7-8c85-b442e986c574/s:/75c5a90a-21d4-46f7-8c85-b442e986c574/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/75c5a90a-21d4-46f7-8c85-b442e986c574/w:/75c5a90a-21d4-46f7-8c85-b442e986c574/w -w /75c5a90a-21d4-46f7-8c85-b442e986c574/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /75c5a90a-21d4-46f7-8c85-b442e986c574/s/script.sh
+ export 'RUSTDOCFLAGS=-D warnings'
+ RUSTDOCFLAGS='-D warnings'
+ cargo --version
info: syncing channel updates for '1.90-x86_64-unknown-linux-gnu'
info: latest update on 2025-09-18, rust version 1.90.0 (1159e78c4 2025-09-14)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-src'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
info: installing component 'rust-src'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'rustfmt'
cargo 1.90.0 (840b83a10 2025-07-30)
+ rustc --version
rustc 1.90.0 (1159e78c4 2025-09-14)
+ cargo fmt --check
Diff in /75c5a90a-21d4-46f7-8c85-b442e986c574/w/crates/radicle-protocol/src/service.rs:221:
SelfConnection,
#[error("outbound connection limit reached when attempting {nid} ({addr})")]
LimitReached { nid: NodeId, addr: Address },
- #[error("attempted connection to {nid}, via {addr} but addresses of this kind are not supported")]
+ #[error(
+ "attempted connection to {nid}, via {addr} but addresses of this kind are not supported"
+ )]
UnsupportedAddress { nid: NodeId, addr: Address },
}
Exit code: 1
{
"response": "finished",
"result": "failure"
}