The `build/macos-sdk.tar.xz` is a slimmed down bundle of the required
SDKs to build Radicle on MacOS.
IOKit, libconv, and libcharset were retrieved from
`phracker/MacOSX-SDKs`, see <https://github.com/phracker/MacOSX-SDKs>.
Since the service performs further I/O (e.g. uses SQLite), it can keep
the reactor runtime thread busy for long periods. Emit a warning if that
is the case.
100 ms is quite relaxed, this is to only catch severe cases and avoid
spamming the log.
Since this is a binary crate, `pub` is not necessary. By removing `pub`
at the boundary of the crate (`src/main.rs`) and working our way in we
obtain tighter boundaries. This enables dead-code elimination and more
liberal lints (see following two commits).
A new module to model the domain of protocol lines and commands
being exchanged is introduced.
This is to increase readability and to pave the way for a
future sans I/O version of the binary crate.
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
In case a `cd` command is to be processed, no replacement of
environment variables in arguments is performed. This means that the
definition of `let mut args` and the replacement itself can be moved
closer to where `args` is then actually used, which is easier to
reason about.
Configuration calls to `escargot` were removed in commit `4894657b`.
An unintentional consequence are spurious failures to invoke freshly
compiled binaries in CLI tests.
Bring back the explicit configuration to remedy.
In the previous refactoring in commit `4894657b`, the order of entries
in `$PATH` was changed unintentionally. Revisit the order and use
nicer APIs to handle paths.
The node being connected to may be blocking the connecting node.
In this case the service will emit an event that says the connecting
node is disconnected.
Check the events for this event as well as `Event::PeerConnected`.
The service learns to consult the policies database to check if a
`NodeId` is blocked.
When a node is blocked the service will prevent any inbound or
outbound connection.
In the case of an inbound connection, a disconnect must be submitted
to the reactor.
In the case of an outbound connection, nodes are filtered out from any
connection lists, and prevented from submitting a connect to the
reactor.
Introduces the ability to explicitly block a peer via the node control
socket. Previously, the node only exposed follow and unfollow commands.
While the underlying policy database schema supported a Block variant,
there was no mechanism to trigger this state via the client handle.
The new block command:
1. Updates the node's follow policy to Block.
2. Immediately disconnects the peer if a session is active.
The previous code would convert the `remote` into a `Component` on
each iteration of the loop.
The conversion now happens outside of the loop and can be reused.
To prepare for future changes, warn users if their config file currently
does not explicitly specify a default seeding policy.
Because there are now potentially multiple warnings generated that all
relate to the configuration file, group these together and adjust the
wording to be more uniform.
The `SeedingPolicy` type now requires a `Scope`, however existing
configurations allow it to not be specified.
Introduce a `radicle::node::config::Scope` type that allows for an
optional `policy::Scope`. The default value resolves to
`policy::Scope::All`. This preserves backwards compatibility for
existing configurations.
As part of the work to change the default scope, one of the tests
surfaced an issue where the topology was Alice <--> Bob <--> Eve,
however because of the previous 'all' scope Alice could receive Eve
references via Bob, but since the scope was changed to 'follow' Alice
would need to have a direct connection to Eve. TODO left here for future
consideration.
The previous implementation used 'all' as the default for scope, this
could lead to surprising behaviour where a user would fetch all
references for cloned and seeded repositories. Instead have a progressive,
safe by default value - where it fetches only 'followed' references. Later
a user can decide to set the scope to 'all'. NOTE: the default policy
scope was not changed from 'all' and is intended to be changed at a
later date.
Previous implementation used the default scope when a scope wasn't
present. Scope is not present when the policy is block, because block
doesn't have a scope. Instead use an empty string when printing the
block policy.
The previous resolution would favour one `Oid` over another, due to
the call to `Option::or`.
This was found to result in scenarios where an identity document being
advertised was older than the identity document that the fetching node
already has, and would not fetch namespaces by newly added delegates.
The resolution logic is updated to handle all cases for these `Oid`s,
and when they are both present, uses a commit graph check to see which
one is the latest.
An e2e test is added to check ensure behaviour works correctly.
Fixes [CVE-2026-0810].
The `gix` crates require updating due to the security vulnerability above.
They require updating together in lock-step so both `radicle-fetch`
and `radicle-oid` are affected.
`radicle-oid` handles the non-exhaustive nature of `ObjectId`.
`radicle-fetch` updates to the new API types, however, this comes with
some updates to the `ls_refs` protocol.
A regression is documented in [gitoxide issue 2429].
The regression highlighted that it is the duty of the caller to also
filter the outcome of ls-refs, and `ref-prefix` is simply an
optimisation.
The ls-refs code is refactored to better represent and handle this operation.
[CVE-2026-0810]: https://www.cve.org/CVERecord?id=CVE-2026-0810
[gitoxide issue 2429]: https://github.com/GitoxideLabs/gitoxide/issues/2429
Better represent the domain by introducing the `RefPrefix` type.
It captures the different `ref-prefix` values that can be used in the
`ls-refs` step of the protocol.
These are turned into their equivalent `ref-prefix` values using
`RefPrefix::into_bstring`.
This better connects the `ProtocolStage::ls_refs` method with the
`ls_refs::run` through the use of the `RefPrefix` type, rather than
any set of `BString` values.
The Git protocol specification states about `ls-refs`[^1]:
> ref-prefix <prefix>
> When specified, only references having a prefix matching one of
> the provided prefixes are displayed. Multiple instances may be
> given, in which case references matching any prefix will be
> shown. Note that this is purely for optimization; a server MAY
> show refs not matching the prefix if it chooses, and clients
> should filter the result themselves.
The `ref-prefix` arguments should not be relied on and post-filtering
after the ls-refs invocation should also be performed.
[^1]: https://git-scm.com/docs/protocol-v2#_ls_refs
The `Responder` is a oneshot channel where it sends one result and the
other side receives that result.
This surfaced that the `AnnounceRefs` command was returning one result
at a time. At the moment, this is only used for a single namespace,
the local user's.
Refactors every command that uses a `Sender` to use a `Responder`
instead. There is an exception for `QueryState` since its usage
differs slightly to the other cases.
To make the usage more ergonomic, constructors for the variants that
require a `Responder` are added.
Introduce a `Responder` type that wraps a
`crossbeam_channel::Sender<Result<T>>`.
It provides a standard constructor and three sending methods: one for
a `Result`, one for an `Ok` value, and one for an `Err` value.
Slightly relax the conditions under which an error is considered to
indicate that the SSH agent is not running, to accommodate differences
in the API of named pipes on Windows vs. Unix domain sockets.
The construction of the debug object is unwieldy, and error prone
(for example, renamed struct members have to be manually renamed
in the serialization code, see "refs" vs. "refsAt").
Use derived serializers where possible to make this easier to maintain.
`radicle-protocol` depends on `cyphernet`, but only uses the module
`cyphernet::addr`, which is a re-export of `cypheraddr`, which is
unnecessary (as `cypheraddr` alone would do), and invites accidentally
pulling in more dependencies via `cyphernet`.
To prevent accidentally depending on further types from `cyphernet`,
change this to more conservativeley depend on `cypheraddr`.