Commit Graph

780 Commits

Author SHA1 Message Date
Lorenz Leutgeb c23a257f3c
clippy: Configure lint `unwrap_used`
By setting `allow-unwrap-in-tests`, we can avoid repeating
`allow(clippy::unwrap_used)` many times over.
2026-04-15 10:06:05 +02:00
Lorenz Leutgeb dbec748c47
clippy: Disallow unused lints
The following clippy lints were allowed in the past but are not
required anymore:
 - box_default
 - large_enum_variant
 - let_unit_value
 - or_fun_call
2026-04-15 10:06:05 +02:00
Lorenz Leutgeb 63f9607423
clippy: Disallow lint `iter_nth_zero` 2026-04-15 10:06:05 +02:00
Lorenz Leutgeb f87d254395
clippy: Disallow lint `identity_op` 2026-04-15 10:06:05 +02:00
Lorenz Leutgeb 33a8c09f78
clippy: Disallow lint `match_like_matches_macro` 2026-04-15 10:06:05 +02:00
Lorenz Leutgeb ca732015fb
clippy: Disallow lints `collapsible_*`
The three lints `collapsible_{if,else_if,match}` are disallowed.
2026-04-15 10:06:05 +02:00
Lorenz Leutgeb 44244dc00f
clippy: Disallow lint `type_complexity`
We just need two exceptions.
2026-04-15 10:06:05 +02:00
Lorenz Leutgeb ffc81154e4
clippy: Disallow lint `enum_variant_names`
We just need one exception.
2026-04-15 10:06:05 +02:00
Lorenz Leutgeb 94f65a71db
cargo: Remove unused dependencies
A number of dependencies were unused, causing confusion. Remove them.
2026-04-15 01:50:14 +02:00
Richard Levitte adfd89f609 cli-test: Respect `CARGO_TARGET_DIR`
`radicle-cli-test` initiates `cargo` builds under the assumption
that the target directory is always within the source directory.
However, the user may have a different idea, specified with the
environment variable `CARGO_TARGET_DIR` (supported by `cargo`, see
https://doc.rust-lang.org/cargo/reference/environment-variables.html).

Add support for `CARGO_TARGET_DIR`, with a fallback to 'target'
at the top of the source tree if `CARGO_TARGET_DIR` is undefined.
2026-04-15 00:18:39 +02:00
Lorenz Leutgeb 80c1bba76f
radicle: Prevent `RAD_SOCKET` from polluting tests
The value of `RAD_SOCKET` influences the outcome of `cargo test`.

Users that set this environment variable to, e.g. point `rad` at
a socket at a custom location, were surprised that execution of
tests would interact with their node.

Split `Home::socket` into two functions. `Home::socket_default` is
"pure" and only dependent on the path represented by `Home`. On the
other hand, `Home::socket_from_env` interprets the environment.

Most users will want to use `Home::socket_from_env`.
2026-04-09 17:53:49 +02:00
Lorenz Leutgeb a2de55cbb9 radicle/crefs: Use `GetPayload` to load
Using `GetPayload`, `GetRawCanonicalRefs` can be implemented
generically.
2026-04-08 11:17:46 +01:00
Lorenz Leutgeb 5167367918 radicle: Introduce `trait GetPayload`
This new trait can be implemented by any struct that allows loading of
payloads. Currently, this only applies to the identity document.
2026-04-08 11:13:28 +01:00
Lorenz Leutgeb aa28567035 radicle/crefs: Refactor `GetCanonicalRefs`
There is only one type that can really construct canonical references,
which is the the identity document. Remove the corresponding method
from the trait and rename it to `GetRawCanonicalRefs` accordingly.
2026-04-08 11:13:28 +01:00
Lorenz Leutgeb ef101d9ab9 radicle/crefs/protect: Module for protected refs
Separate module for the concern of protecting `refs/rad`.

Note that this also fixes a bug, as previously all refs
*starting with* `refs/rad`, such as `refs/radieschen` were protected.
2026-04-08 11:02:25 +01:00
Lorenz Leutgeb e822623dc1 radicle/crefs/rules: Exact patterns for branches
Allows avoiding `try_from`, thus also get rid of one error variant.
2026-04-08 11:02:07 +01:00
Lorenz Leutgeb bfb2858054 radicle/storage: Split `WriteRepository::set_head`
The method `set_head` does two things:
 1. Compute the canonical head and set the default branch to target.
 2. Set the symbolic reference `HEAD` to target the default branch.

Split these two concerns into:
 1. `set_default_branch_to_canonical_head`
 2. `set_head_to_default_branch`
2026-04-08 11:02:07 +01:00
Lorenz Leutgeb 0eba6caf9f radicle: More convenience methods to get default branch 2026-04-08 11:02:07 +01:00
Lorenz Leutgeb 22b2871f64 radicle: Add Version to User Agent
The main motivation behind this change is to get just a little
telemetry information from nodes on the network, namely the version
of Radicle they are running.

This is achieved by rewriting `impl Default for UserAgent` which now
uses the version information provided by the build script also used
in other crates.

Also, a new configuration option `node.userAgent` is added, which
allows users to override the user agent if they so please, or set
the value `null`, which will in turn send the user agent
`/radicle/`, which is not really helpful, and the default prior to
this commit.

Creations of `UserAgent` in the whole workspace is cleaned up. In
order to do that `UserAgent::test` is introduced.
2026-04-02 16:26:46 +01:00
Wiktor Kwapisiewicz 48551cde93 crypto: Use `ssh-agent-lib` for SSH Agent
This makes the `radicle-ssh` crate obsolete.

Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2026-04-02 16:03:23 +01:00
Fintan Halpenny 0080813c91 term: Update inquire to 0.9.4
The `fxhash` crate has become unmaintained and was a transitive
dependency of `inquire`.
The `inquire` crate moved to use `stdlib` instead of `fxhash`[^0].
Update `inquire` to 0.9.4 to get the latest version of the crate.

`cargo deny check` output:
```
error[unmaintained]: fxhash - no longer maintained
    ┌─ /home/fintohaps/Developer/heartwood/Cargo.lock:111:1
    │
111 │ fxhash 0.2.1 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unmaintained advisory detected
    │
    ├ ID: RUSTSEC-2025-0057
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2025-0057
    ├ The fxhash crate is no longer maintained.
      
      The repository is stale and owner is no longer active on GitHub.
      
      Please take a look at [rustc-hash](https://github.com/rust-lang/rustc-hash) instead.
      ```
    ├ Announcement: https://github.com/cbreeden/fxhash/issues/20
    ├ Solution: No safe upgrade is available!
    ├ fxhash v0.2.1
      └── inquire v0.7.5
          └── radicle-term v0.17.0
              └── radicle-cli v0.19.0
                  └── radicle-remote-helper v0.15.0
```

[^0]: 3d5b65422a/CHANGELOG.md?plain=1#L72
2026-04-02 14:46:41 +01:00
Fintan Halpenny 546001253a protocol: Use pastey fork
The `paste` crate is no longer maintained, and the `pastey` fork is a
drop-in replacement.

`cargo deny check` output:
```
error[unmaintained]: paste - no longer maintained
    ┌─ /home/fintohaps/Developer/heartwood/Cargo.lock:239:1
    │
239 │ paste 1.0.15 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unmaintained advisory detected
    │
    ├ ID: RUSTSEC-2024-0436
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2024-0436
    ├ The creator of the crate `paste` has stated in the [`README.md`](https://github.com/dtolnay/paste/blob/master/README.md) 
      that this project is not longer maintained as well as archived the repository
      
      ## Possible Alternative(s)
      
      - [`pastey`]: a fork of paste and is aimed to be a drop-in replacement with additional features for paste crate
      - [`with_builtin_macros`]: crate providing a [superset of `paste`'s functionality including general `macro_rules!` eager expansions](https://docs.rs/with_builtin_macros/0.1.0/with_builtin_macros/macro.with_eager_expansions.html)  and `concat!`/`concat_idents!` macros
      
      [`pastey`]: https://crates.io/crates/pastey
      [`with_builtin_macros`]: https://crates.io/crates/with_builtin_macros
    ├ Announcement: https://github.com/dtolnay/paste
    ├ Solution: No safe upgrade is available!
    ├ paste v1.0.15
      └── (dev) radicle-protocol v0.6.0
          └── radicle-node v0.18.0
              └── (dev) radicle-cli v0.19.0
                  └── radicle-remote-helper v0.15.0
```
2026-04-02 14:46:41 +01:00
Lorenz Leutgeb 96f573b767 cargo: Update dependencies with `cargo update` 2026-04-02 14:46:41 +01:00
Richard Levitte 91590a3287 cli/patch: Show Commit Ranges of Revisions
Each revision now shows a `{base}..{head}` range instead of just the
head.  This is meant to clarify when a patch is rebased, and to be
helpful when one might want to observe changes using 'git range-diff'.
2026-04-02 14:08:44 +01:00
Richard Levitte b8f8cfb319 cli/terminal: Formatting Functions for Ranges
These allow convenient formatting of long/full object identifiers,
as well as formatting ranges.
2026-04-02 14:08:44 +01:00
Lorenz Leutgeb b54fc820e9
radicle/tor: Fixes
Fixes two earlier mistakes:
 1. In `fb18083`, `fn null_to_default` was added, which is only
    conditionally used if the feature "tor" is enabled, so also
    only conditionally compile the function.
 2. In `1e13268`, the `impl Arbitrary` for AddressType` was not
    properly adjusted for the case where the newly introduced
    feature "tor" is disabled.
2026-03-31 23:58:03 +02:00
Lorenz Leutgeb f223afd9d7 radicle: Refactor COB Storage Access
Instead of passing the signer as an argument to many methods on `Store`,
scope the `Store` itself to a signer.

This further allows to differentiate two different access modes on the
store in `radicle::cob::store::access`: `WriteAs` (which requires signer)
and `ReadOnly` (which does not require a signer).

The caches for issues and patches in `radicle::cob::{issue,patch}::Cache`
are concretised by removing the first type parameter, since it was
specific to issues and patches anyway. This was done in this commit as
it touches very similar usage sites.

Make `Device` less prominent, and instead lean more heavily towards
traits from the `signature` crate, such as `Keypair` and `Verifier`
in addition to `Signer`. Trait bounds regarding `Signer` could be
simplified, but this is left for the future.

In `radicle-cli`, the function `term::cob::patches_mut`, which generates
errors with a hint is used instead of the lower-level `Profile::patches_mut`.

Commands `rad issue cache` and `rad patch cache` now construct a
writeable cache on top of a read-only store.

Many knock-on changes are handled as well, to arrive at a clean state.
2026-03-31 17:57:14 +01:00
Lorenz Leutgeb 10a82958ca
node: Explicit default for `AddressConfig`
The intent to drop outgoing connections is modeled as `Option::None`
which is brittle and easy to miss.

Extend `enum AddressConfig` with a variant that is more explicit.
2026-03-31 16:24:22 +02:00
Lorenz Leutgeb fb1808395e
radicle/serde_ext: `fn null_to_default`
This function, taken from
<https://github.com/serde-rs/serde/issues/1098#issuecomment-760711617>,
allows to serialize `null` as the value provided by `Default::default`
for any type that also implements `serde::Deserialize`.
2026-03-31 16:24:22 +02:00
Lorenz Leutgeb 1e132685bc
cargo: Add feature for Tor support 2026-03-31 16:24:22 +02:00
Lorenz Leutgeb 8bac24d6ab
rust/edition/fmt: 2021 → 2024
Reformat code with `rustfmt`, now that the edition changed from
Rust 2021 to Rust 2024.
2026-03-30 16:57:51 +02:00
Lorenz Leutgeb 0494227e75
rust/edition: 2021 → 2024
Switch from Rust 2021 to Rust 2024.

See <https://doc.rust-lang.org/edition-guide/rust-2024/>.

Regarding the added bound `use<>`, see
<https://blog.rust-lang.org/2024/09/05/impl-trait-capture-rules/>.
2026-03-30 16:56:58 +02:00
Fintan Halpenny 263d04b5ea schemars: Update to 0.7.0 2026-03-26 15:32:50 +00:00
Fintan Halpenny 597b514d6c remote-helper: Update to 0.16.0 2026-03-26 15:32:43 +00:00
Fintan Halpenny d685d6f91d cli: Update to 0.20.0 2026-03-26 15:32:43 +00:00
Fintan Halpenny 78908682df node: Update to 0.19.0 2026-03-26 15:32:43 +00:00
Fintan Halpenny 6e40a617de protocol: Update to 0.7.0 2026-03-26 15:28:39 +00:00
Fintan Halpenny 5a2e7841c7 fetch: Update to 0.19.0 2026-03-26 15:28:39 +00:00
Fintan Halpenny 9f91817d25 radicle: Update to 0.23.0 2026-03-26 15:25:11 +00:00
Lorenz Leutgeb 46f4c0f38f
protocol/service: Increase timeout for fetches
A timeout of PT3S was empirically found to be too short to allow for the
verification of Signed References, given that this verification is now
potentially much more costly compared to earlier versions.

PT30S should allow fetching reasonably sized histories, even if they
are on feature level "root".

Note that this is not a timeout for the overall fetch process, but
only for inactivity on the channel during an ongoing fetch.
2026-03-25 19:50:27 +01:00
Lorenz Leutgeb e7467fb15f protocol: SignedRefs upgrades provide `SyncedAt`
When upgrading Signed References via `fn upgrad_sigrefs`, the value of
`RepositoryInfo::synced_at` was not updated. Thus, the caller could not
continue with migrated repositories as usual.

Now that enough information about Signed References is propagated, such
as the head of Signed References after upgrade, is available, it is
possible to construct `SyncedAt`.
2026-03-25 08:19:36 +00:00
Lorenz Leutgeb 6d771abfcc radicle/storage/refs: Remove `RefAt::load`
This is a very thin wrapper around `SignedRefs::load_at` which only
has a single usage in all of the workspace. Remove it.
2026-03-25 08:19:36 +00:00
Lorenz Leutgeb ec36d1c3ae radicle/sigrefs: Merge `SignedRefs{,At}`
Since now all callers expect `SignedRefsAt`, merge the two structs
and name the result just `SignedRefs`.
2026-03-25 08:07:49 +00:00
Lorenz Leutgeb 07011233eb radicle/sigrefs: Use `SignedRefsAt` everywhere
To make more information available to callers, prefer returning
`SignedRefsAt` everywhere.
2026-03-25 08:07:49 +00:00
Lorenz Leutgeb d25fb7f672 radicle/sigrefs/git: Refactor `Committer`
Just slightly more code reuse and a constant.
2026-03-25 08:07:49 +00:00
Lorenz Leutgeb 5d583338c8 radicle/sigrefs/git: Use stable `RAD_LOCAL_TIME`
For stable commits, use the same timestamp as the CLI tests do.
This preserves that commits that are created in the Signed References
module appears as "now" in the output.
2026-03-25 08:07:49 +00:00
Lorenz Leutgeb 86cacfb846 radicle: Have migration repair downgrades
Instead of repairing downgrades, automatic migration could fail.
This occurs when attempting to load signed references, and a downgrade
is detected while coalescing `RepositoryInfo`.

Similarly to how fetch recovers, automatic migration must also recover
by detecting for the downgrade error, and allowing the migration to
happen in this case.
2026-03-25 08:01:29 +00:00
Fintan Halpenny 33db6637b4 radicle: Teach `rad sync` and `rad clone` to accept feature levels
Teach the `rad sync` and `rad clone` commands to accept the
`--signed-refs-feature-level` option. This option configures that
fetch to use the minimum feature level provided when fetching from
other nodes. This overrides the value of
`node.fetch.signedReferences.featureLevel.minimum`, and should only be
used in scenarios where it is necessary to downgrade the security of a
fetch for backwards compatibility.


To achieve this, the `Handle::fetch` method introduces an optional
parameter for threading through the `FeatureLevel`.
2026-03-24 15:07:18 +00:00
Fintan Halpenny ef4ddf06c3 node: Remove `radicle_fetch::Config` from `worker::Config`
The configuration options are now passed through to the worker, and
are no longer needed to initialise.
2026-03-24 14:40:42 +00:00
Fintan Halpenny 07f3d56559 protocol: Allow configuration of `radicle_fetch::Config`
The configuration of the fetch process was only achieved at the setup
of the of the node.
This limits the ability to pass configuration options to the fetch
worker while the node service is running.

This change introduces `radicle_protocol::fetcher::state::FetchConfig`
to allow configuration options to be kept track of. This includes the
previous `timeout` option, but now also includes the
`radicle_fetch::Config`.

The service now produces the `FetchConfig` and passes it through to
the fetch worker.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 81ca4b9eda fetch: Allow upgrading Signed References
After feature levels are introduced to Signed References, and downgrade
attack protections are implemented, new errors are encountered when
reading Signed References that are in a downgraded state.

Such downgrade errors are recoverable by advancing history in a way that
restores the feature level that the history requires.

However, the implementation in `radicle-fetch` must be adjusted to not
abort fetching on downgraded histories, but rather inspect the error in
this case and decide whether continuing the fetching process would
actually help recover from the downgraded state.

The two cases are treated slightly differently for non-delegates and
delegates. Since delegates are crucial for evaluating repository
identity, also the fact that they cannot recover from a downgraded state
is logged at the "info" level.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb e245e3115b fetch: Configure Minimum Feature Level
Add a configuration knob `node.fetch.signedReferences.featureLevel.minimum` to
allow node operators to enforce more strict verification when fetching
Signed References.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 47063057a8 radicle/sigrefs: Automatically Migrate
In order to allow automatic migration to the feature level 'parent',
introduce a way to force writing signed references, even if the
user-controlled refs are unchanged.

To detect the special case of a Signed References history with a single
and root commit (which would otherwise be detected as feature level
'parent', even though the `refs/rad/sigrefs-parent` ref cannot be
written), keep information about the parent commit in `SignedRefs`.

The output of `rad inspect --sigrefs` is changed to match the more
strict interpretation of the feature level for histories with a single
and root commit.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 8b166b2327 fetch: Log on old sigrefs
In hopes of nudging users to upgrade, print a warning if older feature
levels are encountered. However, only do this for delegates, as these
are more critical for the repository, to not log too many warnings.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 7fb032da9b cli/inspect: Show feature level of sigrefs
In order for users to be able to inspect the feature level of Signed
References in a repository, have `rad inspect --sigrefs` attempt to
load Signed References, and, if successful, print the feature level.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 404fe33a88 radicle/sigrefs: Remove `MissingIdentity` error
Feature levels now treat this situation.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 7f19044a72 radicle/sigrefs/write: Treat error to verify head
To prevent from inability to write sigrefs in case of a verification
error, swallow verification errors about the head commit, log, and
carry on writing.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 8bc3ffc0b0 radicle/sigrefs: Detect features when writing
In order to respond to the caller with the correct feature level in
case sigrefs are to be saved but unchanged, the write side needs to
care about feature levels. This is done by sharing more code with the
read side.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 372a78754a radicle/sigrefs: Implement feature detection
To be able to reason about backwards compatibility, downgrade attacks,
and future configurable enforcement of minimum required (security)
features, introduce the concept of a "feature level" in Signed
References.

In this implementation feature levels are assumed to be monotonic, i.e.,
that higher feature levels behave like lower ones, and only add
semantics on top.

Implementing this as an `enum` that is `Ord` flows nicely.

Treatment of the write-side is left for the next commit. Currently,
the write side "promises" `FeatureLevel::Parent`, but is not able
to "keep the promise", since it does not actually inspect the
feature level of the head in case it is unchanged.

CHANGELOG
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb 9a4539fe82 radicle/sigrefs: Find first non-replayed commit
The scenario A₁ ← B₁ ← A₂ ← B₂ would previously have resulted in A₁
being loaded. This is undesriable, since the latest non-replayed commit
is B₁.

The information regarding the order of duplicates, which is preserved by
`seen`, can be used to recover the first commit.
2026-03-24 14:40:42 +00:00
Lorenz Leutgeb b5dc3486db node/wire: Remove `FetchResult` log
Logs produced by this log statement are very hard to decipher, remove
in favour of other logs in the service.
2026-03-24 14:40:10 +00:00
Lorenz Leutgeb 14493cbfbf core: Enable `radicle-oid/qcheck`
Dependents likely expect this.
2026-03-24 13:01:25 +00:00
Fintan Halpenny 9fda8c6d8f radicle: Update to 0.22.1 2026-03-20 16:15:32 +00:00
Adrian Duke c627e68fdb node/reactor: Demote reactor lag log to DEBUG
Demote from WARN to DEBUG as no actions to remedy can be taken by users.
2026-03-19 21:07:51 +00:00
Lorenz Leutgeb a6a3716f5d radicle/node/db: Fix type of IPv6 addresses
Due to a bug introduced in `df8e4e6c88a8bfb6c1ec6b07dcda64093b477cbe`, IPv6
addresses in the configuration file might have ended up in the database
tagged with `type = "dns"`, which is incorrect. The bug was fixed in
`a2e72b48e79d090d33f6c13c485239947de0522e`.

However, Radicle 1.7.0 was released in between those two versions, so a
this migration to repair the entries is added.

Tests are added in `test::migration_8` module. This requires some test
setup, mainly a `Database::memory_up_to_migration` constructor that is only
available to test code.
2026-03-19 21:07:51 +00:00
Lorenz Leutgeb fa1699e5d0 radicle/sigrefs: Revert strict verification of `refs/rad/root`
More sigrefs on the network than previously thought actually are missing
the reference `refs/rad/root`. Revert the change to make this an error,
which was part of commit `d3bc868e84c334f113806df1737f52cc57c5453d`.
2026-03-19 21:07:46 +00:00
Fintan Halpenny d01ff2e79d radicle/node: Do not error on IPv6 without `[]`
IPv6 addresses are already persisted in `config.json` files.
The parsing of these old addresses, e.g. `FE80::0202:B3FF:FE1E:8329:5976` should remain valid.
Emit a warning when they are found.
The output of the address will still enclose the host in `[]`.
2026-03-19 11:52:04 +01:00
Lorenz Leutgeb c237a3fe47
radicle: Fix JSON Schema for `node::Address`
JSON Schema generation via `schemars` was accidentally broken in
`a2e72b4`. Restore the schema.
2026-03-19 00:38:03 +01:00
Fintan Halpenny 9fd4f00c23 remote-helper: Update to 0.15.0 2026-03-18 20:53:00 +00:00
Fintan Halpenny d7e7db35ed cli: Update to 0.19.0 2026-03-18 20:53:00 +00:00
Fintan Halpenny 026dcdb24a node: Update 0.18.0 2026-03-18 20:53:00 +00:00
Fintan Halpenny a9c1c6ef54 protocol: Update to 0.6.0 2026-03-18 20:53:00 +00:00
Fintan Halpenny 8660b2f004 fetch: Update to 0.18.0 2026-03-18 20:53:00 +00:00
Fintan Halpenny 4a731e34e1 radicle: Update to 0.22.0 2026-03-18 20:52:18 +00:00
Fintan Halpenny dafd3527ee git-metadata: Update to 0.2.0 2026-03-18 20:52:18 +00:00
Fintan Halpenny c9450fe84a cob: Update to 0.19.0 2026-03-18 20:44:25 +00:00
Fintan Halpenny 244be71596 core: Update to 0.2.0 2026-03-18 20:44:25 +00:00
Fintan Halpenny 6745865197 crypto: Update to 0.16.0 2026-03-18 20:44:25 +00:00
Defelo a2e72b48e7
node: Serialize and deserialize ipv6 addresses in square brackets 2026-03-18 21:07:10 +01:00
Fintan Halpenny addce859f5 sigrefs/read: fix typo in doc string 2026-03-18 18:03:42 +00:00
Lorenz Leutgeb c824d317e4
radicle: Fix `storage::refs::Error::is_not_found`
Detection of errors of the "not found" kind does not account for the
respective variant in `sigrefs::read::error::Read`. Fix this by adding
it.
2026-03-18 18:55:28 +01:00
Lorenz Leutgeb 748ddade2f
fetch: Make `RemoteRefs` an alias 2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 35d71f5909
fetch: Remove `DelegateStatus`
This `enum` is only used in `state.rs` and a very thin wrapper around
`delegates.contains`.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 363a7231e5
fetch: Remove dead code from `DataRefs` 2026-03-17 21:31:42 +01:00
Fintan Halpenny 725ced09d5 fetch: Prune remotes with sigrefs failures
Previously, trying to load `SignedRefs` for any given remote would
result in a fetch failure.

Teach the fetch to be more resilient by pruning remotes that result in
an error when loading `SignedRefs`, and add the error to the
validation failures.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 6967bf8fca
radicle: Automatically upgrade sigrefs
When enumerating repositories in storage, gracefully handle the
case where the identity root is missing from sigrefs and automatically
migrate.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 20598d39a0
radicle: Remove unused `SyncedAt::load`
This function is unused in heartwood and returns a `git2::Error`. Remove
it.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 0f9eace839
crypto: Remove markers `Verified` and `Unverified`
These are now unused in heartwood.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 304a66311a
radicle: Remove generics for verification markers
`SignedRefs` are now always verified.
2026-03-17 21:31:42 +01:00
Fintan Halpenny 393eca3976 node/e2e: `rad/sigrefs-parent` is not fetched
Introduce a test to ensure that the `SIGREFS_PARENT` reference is
never created during a fetch from another node.
2026-03-17 21:31:42 +01:00
Fintan Halpenny d40fa9a347 radicle/sigrefs: Switch to new implementation 2026-03-17 21:31:42 +01:00
Fintan Halpenny d3bc868e84 radicle/sigrefs: Rewrite Signed References
Split up signed references into its read and write components.

On the write side:
 - Preserve the old behavior of writing references to the blob `/refs`
   and sign over the blob.
 - Ensure `refs/rad/root` is contained in the `/refs` blob.
 - Ensure `refs/rad/sigrefs` is *not* contained in the `/refs` blob.
 - Introduce a new (internal) reference `refs/rad/sigrefs-parent`
   so that no two `/refs` blob are equal, even if they contain
   the same set of (non-internal) refs.

On the read side:
 - Preserve the verification of the signature in `/signature` and
   the reference `refs/rad/root` (if present).
 - Fail verification of `refs/rad/root` is not present.
 - Protect against replay attacks by walking the history of the
   head of `refs/rad/sigrefs`, skipping interpretation of `/refs`
   blobs in case they are identical to a previous `/refs` blob.
   This is achieved by searching for repeated contents of the
   `/signature` blob.

The reference `refs/rad/sigrefs-parent` is never read from or written to
the Git repository in storage.

The pre-existing implementation of signed references did not include
a nonce, thus duplicate but legitimate sets of references could not
be distinguished from maliciously replayed sets of references.

The new implementation uses `radicle-git-metadata` which is moved from
`dev-dependencies` to `dependencies`.
2026-03-17 21:31:42 +01:00
Lorenz Leutgeb 52a660fd3b
node/test: Set `RAD_RNG_SEED` 2026-03-17 19:17:03 +01:00
Matthias Beyer 99d9242122 Use humantime to parse timeouts
In issue

    29c6c6fc8171287faa0079798ba2d6e3e7fd86f3

was noted that it would be nice to use value parsers for the timeouts in
the CLI.

This patch implements this.

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Co-Authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
2026-03-17 11:39:09 +00:00
Defelo 52e5581228 cli: Don't override existing seeding scope in `rad seed` 2026-03-17 10:31:29 +00:00
Defelo 281f92e9ff cli/tests: Add test for `rad clone --scope` 2026-03-17 10:31:29 +00:00
justarandomgeek eea3617781 use `CONIN$` instead of `/dev/tty` on windows 2026-03-17 10:27:30 +00:00
Lorenz Leutgeb 0736977170
node: Migrate IPv6 addresses in database
The format for IPv6 addresses was changed in
df8e4e6c88 to require '[' and ']'.

IPv6 addresses that were stored in the database in the past must be
migrated.
2026-03-16 23:12:58 +01:00
Fintan Halpenny 0c47d06f2d radicle/storage/refs: Strengthen Encapsulation
`radicle::storage::Refs` carries a map from reference names to OIDs, and
there are some invariants.
2026-03-16 14:30:48 +01:00
Lorenz Leutgeb f4495e92bc
radicle/device: `impl Keypair for BoxedSigner`
Most consumers of `Device` are interested in the public key of the
device, and `Keypair` is the trait from `signature` which captures
this, so implement it.

Further, for boxing a signer, introduce a new trait `BoxableSigner`
(to remain dyn-compatible) which additionally requires `Keypair`.
2026-03-16 14:30:48 +01:00
Lorenz Leutgeb 74fa4425a1
crypto: Require `Signer: signature::Signer`
All implementations of `radicle_crypto::Signer` are also
`signature::Signer`. Also, the implementations of `Signer::sign` and
`Signer::try_sign` call each other.

To simplify, make `signature::Signer` a requirement for
`radicle_crypto::Signer`.
2026-03-16 14:30:48 +01:00
Lorenz Leutgeb 06fae85e67
crypto: `impl Signer` based on `Keypair`
Since all signers implement `signature::Keypair`, we can simplify the
implementations of `signature::Signer<ExtendedSignature>`. A blanket
implementation is not possible, because we do not control
`signature::Signer`.
2026-03-16 14:30:48 +01:00
Lorenz Leutgeb f2ad54542e
crypto: `impl signature::KeypairRef` for Signers
The various signers defined in `radicle-crypto` all allow borrowing
the corresponding public key a.k.a. "verifying key". This is captured
by implementing `signature::KeypairRef`, so implement it in addition
to `signature::Signer`.
2026-03-16 14:30:48 +01:00
Fintan Halpenny 768ecf56ba crypto: Add `impl Verifier for PublicKey`
Add `impl Verifier<Signature> for PublicKey`, to allow using the popular
trait from the `signature` crate in verification codepaths.
2026-03-16 14:30:48 +01:00
Fintan Halpenny 01c60388db git-metadata: Add parsing of `CommitData`
This change adds parsing of `CommitData` from raw bytes, i.e. `&[u8]`.
The intended use is to allow the `radicle-*` crates to be able to
parse raw commit data from any underlying Git implementation, such
as the `git2` and `gix` crates.

The tests are broken down into `success` cases, `error` cases, and
`unit` tests.
2026-03-16 14:30:48 +01:00
Fintan Halpenny 58624148d4 git-metadata: Add `CommitData::strip_signatures`
To allow for the verification of a commit signature, the signature
needs to be stripped before converting the commit data to bytes.
2026-03-16 14:30:48 +01:00
Fintan Halpenny 60871de89d git-metadata: Add derivable traits
Add more derivable traits to structs in `radicle-git-metadata` types to
make them easier to use.
2026-03-16 14:30:48 +01:00
Lorenz Leutgeb 0e45347b92
radicle/storage: Improve `Validation` error
`Validation::MismatchedRef` always happens in the context of a remote,
so have it carry the corresponding `RemoteId`.
2026-03-16 14:30:48 +01:00
Fintan Halpenny ba9c09facb radicle/refs: Better `SignedRefs` Encapsulation
Ensure that the public interface of signed references does not leak its
implementation details.

This allows the evolution of the interface in a safer manner, and does
not leak implementation details to the rest of the crate or any
dependents.
2026-03-16 14:30:48 +01:00
Fintan Halpenny 39a58ded05 node/test: Use `Arbitrary` for `SignedRefs`
Ensure the test code does not rely on `SignedRefs` construction, but
rather the `Arbitrary` construction.
2026-03-16 14:30:48 +01:00
Fintan Halpenny f7ff4d8f4e radicle/arbitrary: Move `impl Arbitrary` of refs
Avoid leaking the types of the signed reference types by moving their
`Arbitrary` implementations to a `refs::arbitrary` sub-module.

Since `SignedRefsAt` require a correctly signed payload, a helper
constructor is added: `signed_refs_at`.
In turn, a function, `arbitrary::with_gen` is introduced so that this
constructor can be easily called with a `Gen` value.
2026-03-16 14:30:48 +01:00
Fintan Halpenny b8502397a5 protocol/wire: Remove SignedRefs encoding/decoding
The implementations for `Encode` and `Decode` for `SignedRefs` existed
for when `SignedRefs` was communicated over the wire. This was traded
for communicating `RefsAt` instead. So, these can safely be removed.
2026-03-16 14:30:36 +01:00
Fintan Halpenny ba8d6b8864 radicle/storage: Remove unused Remote methods
Remove the methods and constructors, that are unused, from
`struct Remote`.
2026-03-13 16:19:10 +01:00
Lorenz Leutgeb e78d477bcf
radicle/git: Remove unused `fn remote_refs` 2026-03-13 16:19:10 +01:00
Fintan Halpenny 759a6fb982 radicle: Compile `rad::fork_remote` only for tests
The `rad::fork_remote` function is only used in tests.
2026-03-13 16:19:10 +01:00
Fintan Halpenny cb3ca6225f radicle/CHANGELOG: remove variant typo
The `typos` tool has no way of ignoring a particular typo in a particular file.
Reword the changelog entry so that it does not fire the hook.
2026-03-13 14:50:05 +01:00
Fintan Halpenny 9dbbb01dc6 radicle: remove `TryFrom` 2026-03-13 14:47:24 +01:00
Sebastian Martinez 57da779949 radicle: Add a `load` method to `radicle::profile::Home`
radicle: refactor `Home::load`

- Refactor out getting the subdirectories to ensure they are the same
across `new` and `load`
- Return all missing directories in the error message
- Document `load` and make it `pub`
2026-03-13 14:47:24 +01:00
Matthias Beyer ff85c74eaa cli: Add blank line after issue reply header
This patch adds a blank line to seperate the issue reply header from the
issue reply payload.

This makes visually parsing the output easier.

Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2026-03-12 13:30:09 +00:00
Fintan Halpenny 1b986af006 cli/tests: Refactor workflow test 2026-03-11 10:51:57 +00:00
Adrian Duke fa82bd5f76 cli/tests: Refactor watch command tests 2026-03-11 10:51:57 +00:00
Fintan Halpenny 45e6afd010 cli/tests: Refactor utility command tests
Place utility command tests in their own module.
These commands relate to inspection of state, such as: `rad self`,
`rad config`, `rad inspect`, etc.
2026-03-11 10:51:57 +00:00
Fintan Halpenny d282e0d0f8 cli/tests: Refactor sync command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 7d2842a458 cli/tests: Refactor remote command tests 2026-03-11 10:51:57 +00:00
Adrian Duke c1ab7c386e cli/tests: Refactor policy command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 18d7f99e33 cli/tests: Refactor patch command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 4ffabde605 cli/tests: Refactor node command tests 2026-03-11 10:51:57 +00:00
Adrian Duke b2568f0b47 cli/tests: Refactor jj command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 4753b889dc cli/tests: Refactor issue command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 8bf655ef97 cli/tests: Refactor init command tests 2026-03-11 10:51:57 +00:00
Adrian Duke a1c1b03b66 cli/tests: Refactor inbox command tests 2026-03-11 10:51:57 +00:00
Adrian Duke cd4532ecd5 cli/tests: Refactor id command tests 2026-03-11 10:51:57 +00:00
Adrian Duke dac099e4f1 cli/tests: Refactor git command tests 2026-03-11 10:51:57 +00:00
Adrian Duke d39e485c13 cli/tests: Refactor cob command tests 2026-03-11 10:51:57 +00:00
Adrian Duke 1f3dc6aea0 cli/tests: Refactor clone command tests 2026-03-11 10:51:57 +00:00
Fintan Halpenny 7a1e6a2423 cli/tests: Refactor checkout command tests 2026-03-11 10:51:57 +00:00
Lorenz Leutgeb 5aaf978f97 radicle: Configure database connections on open
Configuration of database connections is not performed on `open`, which
leaves room for error (e.g. to miss specifying configuration).

Methods on `Profile` automatically supply the configuration of the
profile.

In testing code, just using the default configuration suffices.
2026-03-09 09:20:42 +00:00
Lorenz Leutgeb f3afe7b02a radicle/config/sqlite: Use `synchronous = NORMAL`
Change the default value for the `synchronous` pragma from `FULL` to
`NORMAL`.

With this change, SQLite will not aggressively `fsync()` after every
transaction, so there is considerably less disk pressure as disk I/O
can be batched.

See <https://sqlite.org/pragma.html>:
> `WAL` mode is safe from corruption with `synchronous=NORMAL`, and
> probably `DELETE` mode is safe too on modern filesystems. `WAL` mode is
> always consistent with `synchronous=NORMAL`, but `WAL` mode does lose
> durability. A transaction committed in `WAL` mode with
> `synchronous=NORMAL` might roll back following a power loss or system
> crash.
> Transactions are durable across application crashes regardless of the
> synchronous setting or journal mode.

Also:
> You lose durability across power lose with synchronous `NORMAL` in `WAL`
> mode, but that is not important for most applications. Transactions
> are still atomic, consistent, and isolated, which are the most
> important characteristics in most use cases.

So, there is no risk of database corruption, and in the extreme
cases of sudden power loss or system crash, some transaction may
roll back.

See also <https://sqlite.org/wal.html>

Co-authored-by: Yorgos Saslis <yorgos.work@proton.me>
2026-03-09 09:20:42 +00:00
Yorgos Saslis f4aee203ab radicle: Make SQLite pragmas configurable
Expose choosing particular SQLite pragmas via configuration.
2026-03-09 09:20:42 +00:00
Yorgos Saslis 6cc3da95e6 radicle/node/db: Model SQLite `synchronous` pragma
The newly introduced enum models the SQLite pragma of the same name.
2026-03-09 09:04:55 +00:00
Yorgos Saslis d36bf41f25 radicle/node/db: Directly represent SQLite pragmas
Instead of introducing our own names and aliases, directly model SQLite
pragmas with the defaults that they also take in SQLite, to avoid
confusion.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2026-03-09 09:04:55 +00:00
Defelo 9ff67562cb cli: Format IPv6 addresses in square brackets 2026-03-05 15:12:24 +00:00
Defelo df8e4e6c88 node: Parse IPv6 addresses in square brackets 2026-03-05 15:12:24 +00:00
Fintan Halpenny 7c92360842 radicle: fix to schemars of DefaultSeedingPolicy
Use `flatten` to remove the extraneous `Scope2` that shows up in the
JSON schema of the Radicle `Config`.
2026-03-05 15:32:44 +01:00
Fintan Halpenny 6291cae592 cli: add `rad config schema` to the `rad-config` test
Adds the `rad config schema` to the `rad-config` test so that changes
to the schema will result in errors, forcing the implementor to ensure
the changes are correct.
2026-03-05 15:32:44 +01:00
Fintan Halpenny f018b434cb node: control debug serialization of FetcherState
Use proxy structs to control the serialized output of `FetcherState`.

These structs convert data inside the `FetcherState` into friendlier
output for the caller of `rad node debug`.
2026-03-05 15:29:42 +01:00
Fintan Halpenny 9ea1ea2433 Revert "node/debug: Use derived serializers"
This reverts commit 5099c25df7.

The `HostName` of the `RateLimiter` could serialize as an invalid JSON
key, resulting in the command panicking.
2026-03-05 15:29:42 +01:00
Defelo e9245b630d cli: don't override existing seeding scope in `rad clone` 2026-02-23 22:34:03 +00:00
Fintan Halpenny b04f487b3a term: Update to 0.17.0 2026-02-20 14:09:35 +00:00
Fintan Halpenny bab3f82abd fetch: Update to 0.17.0 2026-02-20 14:04:16 +00:00
Fintan Halpenny a0b434c320 localtime: add description in Cargo.toml
The description is required for publishing the crate.
2026-02-20 13:48:14 +00:00
Fintan Halpenny 9dba9130f8 core: use "data-types" instead of "data types"
From the reference[^0]:

> Note: crates.io allows a maximum of 5 keywords. Each keyword must be
> ASCII text, have at most 20 characters, start with an alphanumeric
> character, and only contain letters, numbers, _, - or +.

[0]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-keywords-field
2026-02-20 13:38:34 +00:00
Fintan Halpenny f9a36ef7ac systemd: Update to 0.12.0 2026-02-20 13:11:50 +00:00
Fintan Halpenny 18d6ce9477 protocol: Update 0.5.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny c0ae5e32d9 node: Update to 0.17.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny 963b4ded2b crypto: Update to 0.15.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny 84e9ffe4dc cob: Update to 0.18.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny 186d8d30fe cli: Update to 0.18.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny 3a11074600 radicle: Update to 0.21.0 2026-02-19 21:06:43 +01:00
Fintan Halpenny 1566646762 radcile/cob/identity: mark ApplyError as non_exhaustive 2026-02-19 21:06:43 +01:00
Lorenz Leutgeb 30701cc6fb node/runtime: Make `Runtime::run` more readable
A small refactoring that reorders arms of a match and makes them shorter
by precise imports.
2026-02-18 09:36:49 +00:00
Lorenz Leutgeb 057edf55b8 node/reactor: Introduce `LAG_TIMEOUT`
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.
2026-02-18 09:36:49 +00:00
Lorenz Leutgeb ae06111e07 node/reactor: Rewrite `Runtime::run`
More commentary and slight refactoring in `Runtime::run` to improve
readability.
2026-02-18 09:36:49 +00:00
Lorenz Leutgeb 4d7b942b75
remote-helper: Rename `to_branch_name`
Since `to_branch_name` consumes `self`, it should better be called
`into_branch_name`.

See also
<https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention>.
2026-02-18 00:07:49 +01:00
Lorenz Leutgeb 6d2a99e1ae
remote-helper: Remove Unused Error Variants
Previous minimization of visibility modifiers enables automated
removal of these unused variants.
2026-02-18 00:07:49 +01:00
Lorenz Leutgeb a69420b9b7
remote-helper: Rework Visibility Modifiers
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).
2026-02-18 00:07:49 +01:00
Adrian Duke d36ed7c8af remote-helper/protocol: Introduce Line and Command
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>
2026-02-18 00:07:35 +01:00
Adrian Duke 27493c2229 remote-helper/service: Introduce `NodeSession`
Prefactor to add a trait capturing behaviour of the node.
2026-02-18 00:04:14 +01:00
Adrian Duke 56253b529e remote-helper/service: Introduce `GitService`
Prefactor to introduce `trait GitService` around the behaviour of
`fetch_pack` and `send_pack`.
2026-02-18 00:03:00 +01:00
Adrian Duke bd30e80b9a remote-helper/list: Remove printing to stdio
Prefactor to aid testing.
2026-02-18 00:00:14 +01:00
Lorenz Leutgeb 119445ce6c
cli-test: Move `let mut args` closer to its uses
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.
2026-02-17 20:19:26 +01:00
Lorenz Leutgeb 56ece480ee
cli-test: Remove special handling for `rad`
The special handling for `rad` was introduced in commit
`e63f33489055962845c70976bd9a40d0d84c6b1c` without further comment.

Since we control the `$PATH` for spawning `rad`, and it is clear
that `rad` must be on the path, we do not need any special handing.

See also:
 - https://doc.rust-lang.org/std/process/struct.Command.html#method.new
 - https://github.com/rust-lang/rust/issues/15149
 - https://github.com/rust-lang/rust/issues/37519
2026-02-17 20:16:29 +01:00
Lorenz Leutgeb 3cd1af1dd5
cli-test: Configure `escargot` properly
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.
2026-02-17 18:59:59 +01:00
Lorenz Leutgeb 5aca9bf16a
cli-test: Refactor Path Handling
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.
2026-02-17 18:59:59 +01:00
Adrian Duke d88ef3fa66 e2e: Introduce 3 tests for block command
1. It disconnects an active connection.
2. A blocked peer can not connect to us.
3. A blocked peer can not be fetched from.
2026-02-17 16:12:04 +01:00
Fintan Halpenny a4806f2718 node/test: check remote events for `Event::PeerDisconnected`
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`.
2026-02-17 16:12:04 +01:00
Adrian Duke 1fa14ef529 protocol/service: Use block list for connections
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.
2026-02-17 16:12:04 +01:00
Adrian Duke 94e0a5128d node: Add block command to control socket
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.
2026-02-17 16:12:04 +01:00
Fintan Halpenny 4286590fd9 fetch: move `Component::from` outside of loop
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.
2026-02-17 15:47:31 +01:00
Lorenz Leutgeb 0e9d7607e4 hooks: Enable typos, fix reported errors 2026-02-17 11:35:28 +00:00
Lorenz Leutgeb 5fa68ed814
node: Use `gix_packetline`
`gix-packetline` already is in the dependency closure of `radicle-node`.
Use the well-tested and -used reader instead of ours.
2026-02-16 21:42:59 +01:00
Adrian Duke c96aea0699 node/e2e: Fix test_non_fastforward_identity_doc
This test was flakey.
2026-02-16 21:39:11 +01:00
Adrian Duke 832598ceb7 cli: Warn user about implicit seeding policy
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.
2026-02-16 21:39:11 +01:00
Adrian Duke cee3659ed5 radicle: Introduce `radicle::node::config::Scope`
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.
2026-02-16 21:39:11 +01:00
Adrian Duke 306d0afbfe protocol: Note on peering and fetches
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.
2026-02-16 21:39:11 +01:00
Adrian Duke 0684d1ccdf cli: Changed the default scope from all to followed for clone and seed
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.
2026-02-16 21:39:11 +01:00
Adrian Duke dd13eed1d0 cli: Do not print scope in block table
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.
2026-02-16 21:39:11 +01:00
Adrian Duke b5e8776efd fetch: Improve `refs/rad/id` resolution
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.
2026-02-16 21:39:11 +01:00
Fintan Halpenny 84320919e2 node/tests/e2e: use assert_eq! in test
The use of `assert_eq!` will highlight the differences in the two
values when it fails.
2026-02-16 17:13:39 +00:00
Fintan Halpenny 7862e108b6 Update gix-* crates
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
2026-02-16 17:13:39 +00:00
Fintan Halpenny 391571178e fetch: introduce domain type RefPrefix
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.
2026-02-16 17:11:32 +00:00
Fintan Halpenny 8070f98a5b fetch/transport/ls_refs: Post-filter of references
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
2026-02-16 17:10:40 +00:00
Fintan Halpenny 980ed56186 protocol/service: rename `Responder::new` to `Responder::oneshot`
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.
2026-02-16 13:33:00 +01:00
Fintan Halpenny 0d628a45e2 protocol: refactor to use Responder
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.
2026-02-16 13:33:00 +01:00
Fintan Halpenny b1eedd3b64 protocol/service: introduce Responder type
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.
2026-02-16 13:25:58 +01:00
Fintan Halpenny 61a9b2140f protocol/service: introduce Result synonym
Create a type synonym for `Result<T, Error>`, to simplify result types
being returned by commands in a later change.
2026-02-16 13:25:58 +01:00
Fintan Halpenny 2c1972151d protocol: opaque command error
Refactor `CommandError` to be an opaque, boxed error.
Rename it to `Error`, so that it is imported via `command::Error`.
2026-02-16 13:25:58 +01:00
Fintan Halpenny 38713a8e62 protocol/service: drop `chan` qualifier
Small refactor to drop the `chan` qualifier and use `Sender` directly.
2026-02-16 13:25:58 +01:00
Fintan Halpenny 912a5ca42b protocol/service: create command module
Create a `command` module to house the command related types.
2026-02-16 13:25:58 +01:00
Lorenz Leutgeb fa94638abb radicle/storage/init: Remove placeholder files
These files contain stub texts (see added reference) and only clutter
storage.
2026-02-16 11:16:30 +00:00