From 364c6077bd9a4eae3200c3665ac5b7fc472dba9c Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 1 Dec 2025 12:42:58 +0000 Subject: [PATCH 01/79] fix: clippy errors --- .../src/console/clients/checker/checks/udp.rs | 1 + packages/http-protocol/src/v1/query.rs | 2 +- packages/http-tracker-core/src/services/announce.rs | 8 -------- .../swarm-coordination-registry/src/swarm/coordinator.rs | 2 +- .../src/entry/peer_list.rs | 2 +- packages/tracker-core/src/torrent/services.rs | 2 +- packages/udp-tracker-server/src/event.rs | 2 +- packages/udp-tracker-server/tests/server/contract.rs | 2 +- src/console/ci/e2e/docker.rs | 2 +- src/console/ci/e2e/runner.rs | 2 +- 10 files changed, 9 insertions(+), 16 deletions(-) diff --git a/console/tracker-client/src/console/clients/checker/checks/udp.rs b/console/tracker-client/src/console/clients/checker/checks/udp.rs index 20394d55a..611afafc4 100644 --- a/console/tracker-client/src/console/clients/checker/checks/udp.rs +++ b/console/tracker-client/src/console/clients/checker/checks/udp.rs @@ -29,6 +29,7 @@ pub async fn run(udp_trackers: Vec, timeout: Duration) -> Vec for ErrorKind { }, UdpScrapeError::TrackerCoreWhitelistError { source } => Self::Whitelist(source.to_string()), }, - Error::Internal { location: _, message } => Self::InternalServer(message.to_string()), + Error::Internal { location: _, message } => Self::InternalServer(message.clone()), Error::AuthRequired { location } => Self::TrackerAuthentication(location.to_string()), } } diff --git a/packages/udp-tracker-server/tests/server/contract.rs b/packages/udp-tracker-server/tests/server/contract.rs index da08bc177..e9691c879 100644 --- a/packages/udp-tracker-server/tests/server/contract.rs +++ b/packages/udp-tracker-server/tests/server/contract.rs @@ -251,7 +251,7 @@ mod receiving_an_announce_request { let transaction_id = tx_id.0.to_string(); assert!( - logs_contains_a_line_with(&["ERROR", "UDP TRACKER", &transaction_id.to_string()]), + logs_contains_a_line_with(&["ERROR", "UDP TRACKER", &transaction_id]), "Expected logs to contain: ERROR ... UDP TRACKER ... transaction_id={transaction_id}" ); } diff --git a/src/console/ci/e2e/docker.rs b/src/console/ci/e2e/docker.rs index ce2b1aa99..89d258d2c 100644 --- a/src/console/ci/e2e/docker.rs +++ b/src/console/ci/e2e/docker.rs @@ -82,7 +82,7 @@ impl Docker { let mut port_args: Vec = vec![]; for port in &options.ports { port_args.push("--publish".to_string()); - port_args.push(port.to_string()); + port_args.push(port.clone()); } let args = [initial_args, env_var_args, port_args, [image.to_string()].to_vec()].concat(); diff --git a/src/console/ci/e2e/runner.rs b/src/console/ci/e2e/runner.rs index 624878c70..6275c144b 100644 --- a/src/console/ci/e2e/runner.rs +++ b/src/console/ci/e2e/runner.rs @@ -77,7 +77,7 @@ pub fn run() -> anyhow::Result<()> { // Besides, if we don't use port 0 we should get the port numbers from the tracker configuration. // We could not use docker, but the intention was to create E2E tests including containerization. let options = RunOptions { - env_vars: vec![("TORRUST_TRACKER_CONFIG_TOML".to_string(), tracker_config.to_string())], + env_vars: vec![("TORRUST_TRACKER_CONFIG_TOML".to_string(), tracker_config.clone())], ports: vec![ "6969:6969/udp".to_string(), "7070:7070/tcp".to_string(), From 11721dce92bbf4cc42d389da098a157a1a053922 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 1 Dec 2025 12:43:42 +0000 Subject: [PATCH 02/79] chore(deps): udpate dependencies ``` $ cargo update Updating crates.io index Locking 264 packages to latest compatible versions Updating addr2line v0.24.2 -> v0.25.1 Updating aho-corasick v1.1.3 -> v1.1.4 Adding alloca v0.4.0 Removing android-tzdata v0.1.1 Updating anstream v0.6.19 -> v0.6.21 Updating anstyle v1.0.11 -> v1.0.13 Updating anstyle-query v1.1.3 -> v1.1.5 Updating anstyle-wincon v3.0.9 -> v3.0.11 Updating anyhow v1.0.98 -> v1.0.100 Adding astral-tokio-tar v0.5.6 Updating async-channel v2.3.1 -> v2.5.0 Updating async-compression v0.4.24 -> v0.4.34 Updating async-executor v1.13.2 -> v1.13.3 Updating async-io v2.4.1 -> v2.6.0 Updating async-lock v3.4.0 -> v3.4.1 Updating async-std v1.13.1 -> v1.13.2 Adding async-stream v0.3.6 Adding async-stream-impl v0.3.6 Updating async-trait v0.1.88 -> v0.1.89 Updating atomic v0.6.0 -> v0.6.1 Updating autocfg v1.4.0 -> v1.5.0 Updating axum v0.8.4 -> v0.8.7 Updating axum-core v0.5.2 -> v0.5.5 Updating axum-extra v0.10.1 -> v0.12.2 Updating axum-server v0.7.2 -> v0.7.3 Updating backtrace v0.3.75 -> v0.3.76 Updating bigdecimal v0.4.8 -> v0.4.9 Updating bindgen v0.72.0 -> v0.72.1 Removing bitflags v1.3.2 Removing bitflags v2.9.1 Adding bitflags v2.10.0 Updating blocking v1.6.1 -> v1.6.2 Updating bollard v0.18.1 -> v0.19.4 Adding bollard-buildkit-proto v0.7.0 Updating bollard-stubs v1.47.1-rc.27.3.1 -> v1.49.1-rc.28.4.0 Updating borsh v1.5.7 -> v1.6.0 Updating borsh-derive v1.5.7 -> v1.6.0 Updating brotli v8.0.1 -> v8.0.2 Updating bumpalo v3.18.1 -> v3.19.0 Updating bytemuck v1.23.1 -> v1.24.0 Updating bytes v1.10.1 -> v1.11.0 Updating camino v1.1.10 -> v1.1.12 (available: v1.2.1) Updating castaway v0.2.3 -> v0.2.4 Updating cc v1.2.26 -> v1.2.48 Updating cfg-if v1.0.1 -> v1.0.4 Updating chrono v0.4.41 -> v0.4.42 Updating clap v4.5.40 -> v4.5.53 Updating clap_builder v4.5.40 -> v4.5.53 Updating clap_derive v4.5.40 -> v4.5.49 Updating clap_lex v0.7.5 -> v0.7.6 Adding compression-codecs v0.4.33 Adding compression-core v0.4.31 Updating crc32fast v1.4.2 -> v1.5.0 Updating criterion v0.6.0 -> v0.8.0 Adding criterion-plot v0.8.0 Updating crunchy v0.2.3 -> v0.2.4 Updating crypto-common v0.1.6 -> v0.1.7 Adding darling v0.21.3 Adding darling_core v0.21.3 Adding darling_macro v0.21.3 Updating deranged v0.4.0 -> v0.5.5 Adding dyn-clone v1.0.20 Updating errno v0.3.12 -> v0.3.14 Updating etcetera v0.10.0 -> v0.11.0 Updating event-listener v5.4.0 -> v5.4.1 Adding ferroid v0.8.7 Updating filetime v0.2.25 -> v0.2.26 Adding find-msvc-tools v0.1.5 Updating flate2 v1.1.2 -> v1.1.5 Updating form_urlencoded v1.2.1 -> v1.2.2 Updating frunk v0.4.3 -> v0.4.4 Updating frunk_core v0.4.3 -> v0.4.4 Updating frunk_derives v0.4.3 -> v0.4.4 Updating frunk_proc_macro_helpers v0.1.3 -> v0.1.4 Updating frunk_proc_macros v0.1.3 -> v0.1.4 Updating fs-err v3.1.1 -> v3.2.0 Updating futures-lite v2.6.0 -> v2.6.1 Updating getrandom v0.3.3 -> v0.3.4 Updating gimli v0.31.1 -> v0.32.3 Updating glob v0.3.2 -> v0.3.3 Updating h2 v0.4.10 -> v0.4.12 Updating half v2.6.0 -> v2.7.1 Removing hashbrown v0.15.4 Adding hashbrown v0.15.5 Adding hashbrown v0.16.1 Updating hermit-abi v0.5.1 -> v0.5.2 Updating hex-literal v1.0.0 -> v1.1.0 Updating home v0.5.11 -> v0.5.12 Updating http v1.3.1 -> v1.4.0 Updating hyper v1.6.0 -> v1.8.1 Adding hyper-timeout v0.5.2 Updating hyper-util v0.1.14 -> v0.1.18 Updating iana-time-zone v0.1.63 -> v0.1.64 Updating icu_collections v2.0.0 -> v2.1.1 Updating icu_locale_core v2.0.0 -> v2.1.1 Updating icu_normalizer v2.0.0 -> v2.1.1 Updating icu_normalizer_data v2.0.0 -> v2.1.1 Updating icu_properties v2.0.1 -> v2.1.1 Updating icu_properties_data v2.0.1 -> v2.1.1 Updating icu_provider v2.0.0 -> v2.1.1 Updating idna v1.0.3 -> v1.1.0 Updating indexmap v2.9.0 -> v2.12.1 Updating iri-string v0.7.8 -> v0.7.9 Updating is-terminal v0.4.16 -> v0.4.17 Updating is_terminal_polyfill v1.70.1 -> v1.70.2 Adding itertools v0.14.0 Updating jobserver v0.1.33 -> v0.1.34 Updating js-sys v0.3.77 -> v0.3.83 Updating libc v0.2.172 -> v0.2.177 Updating libloading v0.8.8 -> v0.8.9 Updating libredox v0.1.3 -> v0.1.10 Updating libsqlite3-sys v0.34.0 -> v0.35.0 Updating libz-sys v1.1.22 -> v1.1.23 Updating linux-raw-sys v0.9.4 -> v0.11.0 Updating litemap v0.8.0 -> v0.8.1 Updating lock_api v0.4.13 -> v0.4.14 Updating log v0.4.27 -> v0.4.28 Updating memchr v2.7.4 -> v2.7.6 Updating mio v1.0.4 -> v1.1.0 Updating mockall v0.13.1 -> v0.14.0 Updating mockall_derive v0.13.1 -> v0.14.0 Updating nu-ansi-term v0.46.0 -> v0.50.3 Adding num v0.4.3 Adding num-complex v0.4.6 Adding num-iter v0.1.45 Adding num-rational v0.4.2 Updating object v0.36.7 -> v0.37.3 Updating once_cell_polyfill v1.70.1 -> v1.70.2 Updating openssl v0.10.73 -> v0.10.75 Updating openssl-sys v0.9.109 -> v0.9.111 Removing overload v0.1.1 Updating owo-colors v4.2.1 -> v4.2.3 Adding page_size v0.6.0 Updating parking_lot v0.12.4 -> v0.12.5 Updating parking_lot_core v0.9.11 -> v0.9.12 Updating pem v3.0.5 -> v3.0.6 Updating percent-encoding v2.3.1 -> v2.3.2 Adding pin-project v1.1.10 Adding pin-project-internal v1.1.10 Updating polling v3.8.0 -> v3.11.0 Updating potential_utf v0.1.2 -> v0.1.4 Updating proc-macro-crate v3.3.0 -> v3.4.0 Updating proc-macro2 v1.0.95 -> v1.0.103 Adding prost v0.14.2 Adding prost-derive v0.14.2 Adding prost-types v0.14.2 Updating quote v1.0.40 -> v1.0.42 Updating r-efi v5.2.0 -> v5.3.0 Updating r2d2_sqlite v0.29.0 -> v0.31.0 Updating rand v0.9.1 -> v0.9.2 Updating rayon v1.10.0 -> v1.11.0 Updating rayon-core v1.12.1 -> v1.13.0 Removing redox_syscall v0.3.5 Removing redox_syscall v0.5.12 Adding redox_syscall v0.5.18 Adding ref-cast v1.0.25 Adding ref-cast-impl v1.0.25 Updating regex v1.11.1 -> v1.12.2 Updating regex-automata v0.4.9 -> v0.4.13 Updating regex-syntax v0.8.5 -> v0.8.8 Updating reqwest v0.12.20 -> v0.12.24 Adding rstest v0.26.1 Adding rstest_macros v0.26.1 Updating rusqlite v0.36.0 -> v0.37.0 Updating rust_decimal v1.37.1 -> v1.39.0 Updating rustc-demangle v0.1.25 -> v0.1.26 Updating rustix v1.0.7 -> v1.1.2 Updating rustls v0.23.27 -> v0.23.35 Updating rustls-native-certs v0.8.1 -> v0.8.2 Updating rustls-pki-types v1.12.0 -> v1.13.1 Updating rustls-webpki v0.103.3 -> v0.103.8 Updating rustversion v1.0.21 -> v1.0.22 Updating schannel v0.1.27 -> v0.1.28 Adding schemars v0.9.0 Adding schemars v1.1.0 Updating security-framework v3.2.0 -> v3.5.1 Updating security-framework-sys v2.14.0 -> v2.15.0 Updating semver v1.0.26 -> v1.0.27 Updating serde v1.0.219 -> v1.0.228 Updating serde_bytes v0.11.17 -> v0.11.19 Adding serde_core v1.0.228 Updating serde_derive v1.0.219 -> v1.0.228 Updating serde_html_form v0.2.7 -> v0.2.8 Updating serde_json v1.0.140 -> v1.0.145 Updating serde_path_to_error v0.1.17 -> v0.1.20 Adding serde_spanned v1.0.3 Updating serde_with v3.12.0 -> v3.16.1 Updating serde_with_macros v3.12.0 -> v3.16.1 Updating signal-hook-registry v1.4.5 -> v1.4.7 Adding simd-adler32 v0.3.7 Updating slab v0.4.9 -> v0.4.11 Adding socket2 v0.6.1 Updating stable_deref_trait v1.2.0 -> v1.2.1 Updating syn v2.0.102 -> v2.0.111 Updating tempfile v3.20.0 -> v3.23.0 Updating terminal_size v0.4.2 -> v0.4.3 Updating testcontainers v0.24.0 -> v0.26.0 Updating thiserror v2.0.12 -> v2.0.17 Updating thiserror-impl v2.0.12 -> v2.0.17 Updating thread_local v1.1.8 -> v1.1.9 Updating time v0.3.41 -> v0.3.44 Updating time-core v0.1.4 -> v0.1.6 Updating time-macros v0.2.22 -> v0.2.24 Updating tinystr v0.8.1 -> v0.8.2 Updating tinyvec v1.9.0 -> v1.10.0 Updating tokio v1.45.1 -> v1.48.0 Updating tokio-macros v2.5.0 -> v2.6.0 Updating tokio-rustls v0.26.2 -> v0.26.4 Removing tokio-tar v0.3.1 Updating tokio-util v0.7.15 -> v0.7.17 Adding toml v0.9.8 Adding toml_datetime v0.7.3 Adding toml_edit v0.23.7 Adding toml_parser v1.0.4 Adding toml_writer v1.0.4 Adding tonic v0.14.2 Adding tonic-prost v0.14.2 Updating tower-http v0.6.6 -> v0.6.7 Updating tracing v0.1.41 -> v0.1.43 Updating tracing-attributes v0.1.29 -> v0.1.31 Updating tracing-core v0.1.34 -> v0.1.35 Updating tracing-subscriber v0.3.19 -> v0.3.22 Updating typenum v1.18.0 -> v1.19.0 Updating unicode-ident v1.0.18 -> v1.0.22 Updating unicode-width v0.2.1 -> v0.2.2 Adding ureq v3.1.4 Adding ureq-proto v0.5.3 Updating url v2.5.4 -> v2.5.7 Adding utf-8 v0.7.6 Updating uuid v1.17.0 -> v1.18.1 Updating value-bag v1.11.1 -> v1.12.0 Removing wasi v0.14.2+wasi-0.2.4 Adding wasip2 v1.0.1+wasi-0.2.4 Updating wasm-bindgen v0.2.100 -> v0.2.106 Removing wasm-bindgen-backend v0.2.100 Updating wasm-bindgen-futures v0.4.50 -> v0.4.56 Updating wasm-bindgen-macro v0.2.100 -> v0.2.106 Updating wasm-bindgen-macro-support v0.2.100 -> v0.2.106 Updating wasm-bindgen-shared v0.2.100 -> v0.2.106 Updating web-sys v0.3.77 -> v0.3.83 Adding web-time v1.1.0 Adding webpki-roots v1.0.4 Updating winapi-util v0.1.9 -> v0.1.11 Updating windows-core v0.61.2 -> v0.62.2 Updating windows-implement v0.60.0 -> v0.60.2 Updating windows-interface v0.59.1 -> v0.59.3 Updating windows-link v0.1.1 -> v0.2.1 Updating windows-registry v0.5.2 -> v0.6.1 Updating windows-result v0.3.4 -> v0.4.1 Updating windows-strings v0.4.2 -> v0.5.1 Adding windows-sys v0.60.2 Adding windows-sys v0.61.2 Updating windows-targets v0.53.0 -> v0.53.5 Updating windows_aarch64_gnullvm v0.53.0 -> v0.53.1 Updating windows_aarch64_msvc v0.53.0 -> v0.53.1 Updating windows_i686_gnu v0.53.0 -> v0.53.1 Updating windows_i686_gnullvm v0.53.0 -> v0.53.1 Updating windows_i686_msvc v0.53.0 -> v0.53.1 Updating windows_x86_64_gnu v0.53.0 -> v0.53.1 Updating windows_x86_64_gnullvm v0.53.0 -> v0.53.1 Updating windows_x86_64_msvc v0.53.0 -> v0.53.1 Updating winnow v0.7.11 -> v0.7.14 Adding wit-bindgen v0.46.0 Removing wit-bindgen-rt v0.39.0 Updating writeable v0.6.1 -> v0.6.2 Updating xattr v1.5.0 -> v1.6.1 Updating yoke v0.8.0 -> v0.8.1 Updating yoke-derive v0.8.0 -> v0.8.1 Updating zerocopy v0.8.25 -> v0.8.31 Updating zerocopy-derive v0.8.25 -> v0.8.31 Updating zeroize v1.8.1 -> v1.8.2 Updating zerotrie v0.2.2 -> v0.2.3 Updating zerovec v0.11.2 -> v0.11.5 Updating zerovec-derive v0.11.1 -> v0.11.2 Updating zstd-sys v2.0.15+zstd.1.5.7 -> v2.0.16+zstd.1.5.7 note: pass `--verbose` to see 6 unchanged dependencies behind latest ``` --- Cargo.lock | 1870 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 1187 insertions(+), 683 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b523c8b60..62d10c72f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -53,16 +53,19 @@ dependencies = [ ] [[package]] -name = "allocator-api2" -version = "0.2.21" +name = "alloca" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] [[package]] -name = "android-tzdata" -version = "0.1.1" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android_system_properties" @@ -81,9 +84,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -96,9 +99,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -111,29 +114,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "approx" @@ -182,6 +185,22 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "astral-tokio-tar" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec179a06c1769b1e42e1e2cbe74c7dcdb3d6383c838454d063eaac5bbb7ebbe5" +dependencies = [ + "filetime", + "futures-core", + "libc", + "portable-atomic", + "rustc-hash", + "tokio", + "tokio-stream", + "xattr", +] + [[package]] name = "async-attributes" version = "1.1.2" @@ -205,9 +224,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -217,25 +236,22 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.24" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" +checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473" dependencies = [ - "brotli", - "flate2", + "compression-codecs", + "compression-core", "futures-core", - "memchr", "pin-project-lite", "tokio", - "zstd", - "zstd-safe", ] [[package]] name = "async-executor" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ "async-task", "concurrent-queue", @@ -251,7 +267,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-executor", "async-io", "async-lock", @@ -263,11 +279,11 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", @@ -276,26 +292,25 @@ dependencies = [ "polling", "rustix", "slab", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-std" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-attributes", "async-channel 1.9.0", @@ -318,6 +333,28 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "async-task" version = "4.7.1" @@ -326,20 +363,20 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "atomic" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ "bytemuck", ] @@ -352,15 +389,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ "axum-core", "axum-macros", @@ -378,8 +415,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -404,9 +440,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -415,7 +451,6 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -424,27 +459,27 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.10.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d" +checksum = "dbfe9f610fe4e99cf0cfcd03ccf8c63c28c616fe714d80475ef731f3b13dd21b" dependencies = [ "axum", "axum-core", "bytes", "form_urlencoded", + "futures-core", "futures-util", "http", "http-body", "http-body-util", "mime", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_html_form", "serde_path_to_error", - "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -455,14 +490,14 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "axum-server" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab" +checksum = "c1ab4a3ec9ea8a657c72d99a03a824af695bd0fb5ec639ccbd9cd3543b41a5f9" dependencies = [ "arc-swap", "bytes", @@ -482,9 +517,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -492,7 +527,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -518,9 +553,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bigdecimal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" +checksum = "560f42649de9fa436b73517378a147ec21f6c997a546581df4b4b31677828934" dependencies = [ "autocfg", "libm", @@ -537,11 +572,11 @@ checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" [[package]] name = "bindgen" -version = "0.72.0" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.9.1", + "bitflags", "cexpr", "clang-sys", "itertools 0.13.0", @@ -550,7 +585,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -561,15 +596,9 @@ checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bittorrent-http-tracker-core" @@ -585,7 +614,7 @@ dependencies = [ "mockall", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-tracker-clock", @@ -610,7 +639,7 @@ dependencies = [ "percent-encoding", "serde", "serde_bencode", - "thiserror 2.0.12", + "thiserror 2.0.17", "torrust-tracker-clock", "torrust-tracker-configuration", "torrust-tracker-contrib-bencode", @@ -646,7 +675,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "serde_repr", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "torrust-tracker-configuration", "torrust-tracker-located-error", @@ -668,11 +697,11 @@ dependencies = [ "r2d2", "r2d2_mysql", "r2d2_sqlite", - "rand 0.9.1", + "rand 0.9.2", "serde", "serde_json", "testcontainers", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-rest-tracker-api-client", @@ -703,9 +732,9 @@ dependencies = [ "futures", "lazy_static", "mockall", - "rand 0.9.1", + "rand 0.9.2", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-tracker-clock", @@ -751,11 +780,11 @@ dependencies = [ [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-task", "futures-io", "futures-lite", @@ -783,13 +812,17 @@ dependencies = [ [[package]] name = "bollard" -version = "0.18.1" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" +checksum = "87a52479c9237eb04047ddb94788c41ca0d26eaff8b697ecfbb4c32f7fdc3b1b" dependencies = [ + "async-stream", "base64 0.22.1", + "bitflags", + "bollard-buildkit-proto", "bollard-stubs", "bytes", + "chrono", "futures-core", "futures-util", "hex", @@ -802,7 +835,9 @@ dependencies = [ "hyper-util", "hyperlocal", "log", + "num", "pin-project-lite", + "rand 0.9.2", "rustls", "rustls-native-certs", "rustls-pemfile", @@ -812,30 +847,51 @@ dependencies = [ "serde_json", "serde_repr", "serde_urlencoded", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", + "tokio-stream", "tokio-util", + "tonic", "tower-service", "url", "winapi", ] +[[package]] +name = "bollard-buildkit-proto" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tonic-prost", + "ureq", +] + [[package]] name = "bollard-stubs" -version = "1.47.1-rc.27.3.1" +version = "1.49.1-rc.28.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da" +checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623" dependencies = [ + "base64 0.22.1", + "bollard-buildkit-proto", + "bytes", + "chrono", + "prost", "serde", + "serde_json", "serde_repr", "serde_with", ] [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" dependencies = [ "borsh-derive", "cfg_aliases", @@ -843,22 +899,22 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "brotli" -version = "8.0.1" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -892,9 +948,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecheck" @@ -920,9 +976,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -932,15 +988,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "camino" -version = "1.1.10" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" +checksum = "dd0b03af37dad7a14518b7691d81acb0f8222604ad3d1b02f6b4bed5188c0cd5" dependencies = [ "serde", ] @@ -953,19 +1009,20 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "castaway" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.2.26" +version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -982,9 +1039,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -994,11 +1051,10 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", "serde", @@ -1055,9 +1111,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.40" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -1065,9 +1121,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -1077,21 +1133,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cmake" @@ -1121,6 +1177,26 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "compression-codecs" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "memchr", + "zstd", + "zstd-safe", +] + +[[package]] +name = "compression-core" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1167,9 +1243,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -1184,7 +1260,7 @@ dependencies = [ "cast", "ciborium", "clap", - "criterion-plot", + "criterion-plot 0.5.0", "futures", "is-terminal", "itertools 0.10.5", @@ -1204,18 +1280,20 @@ dependencies = [ [[package]] name = "criterion" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" +checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" dependencies = [ + "alloca", "anes", "cast", "ciborium", "clap", - "criterion-plot", + "criterion-plot 0.8.0", "itertools 0.13.0", "num-traits", "oorandom", + "page_size", "plotters", "rayon", "regex", @@ -1236,6 +1314,16 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "criterion-plot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" +dependencies = [ + "cast", + "itertools 0.13.0", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -1304,15 +1392,15 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -1324,8 +1412,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -1339,7 +1437,21 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.102", + "syn 2.0.111", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.111", ] [[package]] @@ -1348,9 +1460,20 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -1369,12 +1492,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -1394,7 +1517,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", "unicode-xid", ] @@ -1406,7 +1529,7 @@ checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -1433,7 +1556,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -1453,6 +1576,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" version = "1.15.0" @@ -1486,23 +1615,22 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "etcetera" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" +checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96" dependencies = [ "cfg-if", - "home", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1513,9 +1641,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -1528,7 +1656,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1550,6 +1678,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ferroid" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e9414a6ae93ef993ce40a1e02944f13d4508e2bf6f1ced1580ce6910f08253" +dependencies = [ + "portable-atomic", + "rand 0.9.2", + "web-time", +] + [[package]] name = "figment" version = "0.10.19" @@ -1561,28 +1700,34 @@ dependencies = [ "pear", "serde", "tempfile", - "toml", + "toml 0.8.23", "uncased", "version_check", ] [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "libz-sys", @@ -1618,9 +1763,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1653,9 +1798,9 @@ checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "frunk" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874b6a17738fc273ec753618bac60ddaeac48cb1d7684c3e7bd472e57a28b817" +checksum = "28aef0f9aa070bce60767c12ba9cb41efeaf1a2bc6427f87b7d83f11239a16d7" dependencies = [ "frunk_core", "frunk_derives", @@ -1665,53 +1810,53 @@ dependencies = [ [[package]] name = "frunk_core" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3529a07095650187788833d585c219761114005d5976185760cf794d265b6a5c" +checksum = "476eeaa382e3462b84da5d6ba3da97b5786823c2d0d3a0d04ef088d073da225c" dependencies = [ "serde", ] [[package]] name = "frunk_derives" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e99b8b3c28ae0e84b604c75f721c21dc77afb3706076af5e8216d15fd1deaae3" +checksum = "a0b4095fc99e1d858e5b8c7125d2638372ec85aa0fe6c807105cf10b0265ca6c" dependencies = [ "frunk_proc_macro_helpers", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "frunk_proc_macro_helpers" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a956ef36c377977e512e227dcad20f68c2786ac7a54dacece3746046fea5ce" +checksum = "1952b802269f2db12ab7c0bd328d0ae8feaabf19f352a7b0af7bb0c5693abfce" dependencies = [ "frunk_core", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "frunk_proc_macros" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e86c2c9183662713fea27ea527aad20fb15fee635a71081ff91bf93df4dc51" +checksum = "3462f590fa236005bd7ca4847f81438bd6fe0febd4d04e11968d4c2e96437e78" dependencies = [ "frunk_core", "frunk_proc_macro_helpers", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "fs-err" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7be93788013f265201256d58f04936a8079ad5dc898743aa20525f503b683" +checksum = "62d91fd049c123429b018c47887d3f75a265540dd3c30ba9cb7bae9197edb03a" dependencies = [ "autocfg", "tokio", @@ -1773,9 +1918,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "fastrand", "futures-core", @@ -1792,7 +1937,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -1849,32 +1994,32 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "gloo-timers" @@ -1890,9 +2035,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1900,7 +2045,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.9.0", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -1909,12 +2054,13 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy 0.8.31", ] [[package]] @@ -1934,22 +2080,28 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "hashlink" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -1960,9 +2112,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1972,27 +2124,26 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcaaec4551594c969335c98c903c1397853d4198408ea609190f420500f6be71" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2033,13 +2184,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -2047,6 +2199,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -2083,6 +2236,19 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -2101,9 +2267,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.14" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" dependencies = [ "base64 0.22.1", "bytes", @@ -2117,7 +2283,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.1", "system-configuration", "tokio", "tower-service", @@ -2142,9 +2308,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2166,9 +2332,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -2179,9 +2345,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -2192,11 +2358,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2207,42 +2372,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2258,9 +2419,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2290,13 +2451,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.1", "serde", + "serde_core", ] [[package]] @@ -2331,9 +2493,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -2341,13 +2503,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2358,9 +2520,9 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2381,26 +2543,35 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.15" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -2423,18 +2594,18 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.0", + "windows-link", ] [[package]] @@ -2445,20 +2616,20 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.1", + "bitflags", "libc", - "redox_syscall 0.5.12", + "redox_syscall", ] [[package]] name = "libsqlite3-sys" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91632f3b4fb6bd1d72aa3d78f41ffecfcf2b1a6648d8c241dbe7dbfaf4875e15" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" dependencies = [ "cc", "pkg-config", @@ -2467,9 +2638,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" dependencies = [ "cc", "pkg-config", @@ -2478,15 +2649,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "local-ip-address" @@ -2496,25 +2667,24 @@ checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" dependencies = [ "libc", "neli", - "thiserror 2.0.12", + "thiserror 2.0.17", "windows-sys 0.59.0", ] [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" dependencies = [ "value-bag", ] @@ -2525,7 +2695,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -2536,9 +2706,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "miette" @@ -2567,7 +2737,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -2589,24 +2759,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "mockall" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" +checksum = "f58d964098a5f9c6b63d0798e5372fd04708193510a7af313c22e9f29b7b620b" dependencies = [ "cfg-if", "downcast", @@ -2618,14 +2789,14 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" +checksum = "ca41ce716dda6a9be188b385aa78ee5260fc25cd3802cb2a8afdc6afbe6b6dbf" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -2657,7 +2828,7 @@ dependencies = [ "percent-encoding", "serde", "serde_json", - "socket2", + "socket2 0.5.10", "twox-hash", "url", ] @@ -2668,14 +2839,14 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63c3512cf11487168e0e9db7157801bf5273be13055a9cc95356dc9e0035e49c" dependencies = [ - "darling", + "darling 0.20.11", "heck", "num-bigint", "proc-macro-crate", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", "termcolor", "thiserror 1.0.69", ] @@ -2689,7 +2860,7 @@ dependencies = [ "base64 0.21.7", "bigdecimal", "bindgen", - "bitflags 2.9.1", + "bitflags", "bitvec", "btoi", "byteorder", @@ -2788,12 +2959,25 @@ checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] @@ -2806,6 +2990,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2821,6 +3014,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2832,9 +3047,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -2847,9 +3062,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -2859,11 +3074,11 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.9.1", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -2880,7 +3095,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -2891,9 +3106,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -2902,16 +3117,20 @@ dependencies = [ ] [[package]] -name = "overload" -version = "0.1.1" +name = "owo-colors" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" [[package]] -name = "owo-colors" -version = "4.2.1" +name = "page_size" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] [[package]] name = "parking" @@ -2921,9 +3140,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2931,15 +3150,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.12", + "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2964,7 +3183,7 @@ dependencies = [ "regex", "regex-syntax", "structmeta", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -2987,24 +3206,24 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" @@ -3044,6 +3263,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -3103,17 +3342,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.8.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", "rustix", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3133,9 +3371,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -3152,7 +3390,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.25", + "zerocopy 0.8.31", ] [[package]] @@ -3193,11 +3431,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit", + "toml_edit 0.23.7", ] [[package]] @@ -3219,14 +3457,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -3239,11 +3477,43 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", "version_check", "yansi", ] +[[package]] +name = "prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "101fec8d036f8d9d4a1e8ebf90d566d1d798f3b1aa379d2576a54a0d9acea5bd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d93e596a829ebe00afa41c3a056e6308d6b8a4c7d869edf184e2c91b1ba564" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "prost-types" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d7b7346e150de32340ae3390b8b3ffa37ad93ec31fb5dad86afe817619e4e7" +dependencies = [ + "prost", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -3277,18 +3547,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "r2d2" @@ -3313,9 +3583,9 @@ dependencies = [ [[package]] name = "r2d2_sqlite" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35006423374afbd4b270acddcbf1e28e60f6bdaaad10c2888b8fd2fba035213c" +checksum = "63417e83dc891797eea3ad379f52a5986da4bca0d6ef28baf4d14034dd111b0c" dependencies = [ "r2d2", "rusqlite", @@ -3341,9 +3611,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -3384,14 +3654,14 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -3399,9 +3669,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3409,27 +3679,38 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] -name = "redox_syscall" -version = "0.5.12" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "bitflags 2.9.1", + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -3439,9 +3720,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -3450,9 +3731,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "relative-path" @@ -3471,9 +3752,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.20" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64 0.22.1", "bytes", @@ -3571,10 +3852,21 @@ checksum = "6fc39292f8613e913f7df8fa892b8944ceb47c247b78e1b1ae2f09e019be789d" dependencies = [ "futures-timer", "futures-util", - "rstest_macros", + "rstest_macros 0.25.0", "rustc_version", ] +[[package]] +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros 0.26.1", +] + [[package]] name = "rstest_macros" version = "0.25.0" @@ -3589,17 +3881,35 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.102", + "syn 2.0.111", + "unicode-ident", +] + +[[package]] +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.111", "unicode-ident", ] [[package]] name = "rusqlite" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de23c3319433716cf134eed225fe9986bc24f63bed9be9f20c329029e672dc7" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ - "bitflags 2.9.1", + "bitflags", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -3609,9 +3919,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.37.1" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "borsh", @@ -3625,9 +3935,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -3646,23 +3956,24 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.27" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "log", "once_cell", "ring", "rustls-pki-types", @@ -3673,14 +3984,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", + "security-framework 3.5.1", ] [[package]] @@ -3694,18 +4005,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -3714,9 +4025,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -3741,11 +4052,11 @@ checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3757,6 +4068,30 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3775,7 +4110,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -3784,11 +4119,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "bitflags 2.9.1", + "bitflags", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3797,9 +4132,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -3807,16 +4142,17 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -3832,58 +4168,70 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "serde_html_form" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4" +checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.9.0", + "indexmap 2.12.1", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.12.1", "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] @@ -3894,7 +4242,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -3906,6 +4254,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3920,17 +4277,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.12.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", + "indexmap 2.12.1", + "schemars 0.9.0", + "schemars 1.1.0", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -3938,14 +4296,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.12.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ - "darling", + "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -3987,13 +4345,19 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simdutf8" version = "0.1.5" @@ -4008,12 +4372,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -4031,11 +4392,21 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -4058,7 +4429,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -4069,7 +4440,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -4122,9 +4493,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.102" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -4148,7 +4519,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -4157,7 +4528,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.1", + "bitflags", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -4197,15 +4568,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4219,12 +4590,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4235,18 +4606,20 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bb7577dca13ad86a78e8271ef5d322f37229ec83b8d98da6d996c588a1ddb1" +checksum = "a347cac4368ba4f1871743adb27dc14829024d26b1763572404726b0b9943eb8" dependencies = [ + "astral-tokio-tar", "async-trait", "bollard", - "bollard-stubs", "bytes", "docker_credential", "either", "etcetera", + "ferroid", "futures", + "itertools 0.14.0", "log", "memchr", "parse-display", @@ -4254,10 +4627,9 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-stream", - "tokio-tar", "tokio-util", "url", ] @@ -4269,7 +4641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" dependencies = [ "unicode-linebreak", - "unicode-width 0.2.1", + "unicode-width 0.2.2", ] [[package]] @@ -4283,11 +4655,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -4298,35 +4670,34 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -4339,15 +4710,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -4355,9 +4726,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -4375,9 +4746,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -4390,30 +4761,29 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -4428,9 +4798,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -4447,26 +4817,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-tar" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" -dependencies = [ - "filetime", - "futures-core", - "libc", - "redox_syscall 0.3.5", - "tokio", - "tokio-stream", - "xattr", -] - [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -4482,9 +4837,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap 2.12.1", + "serde_core", + "serde_spanned 1.0.3", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow", ] [[package]] @@ -4496,26 +4866,102 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.12.1", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_write", "winnow", ] +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap 2.12.1", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + +[[package]] +name = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2 0.6.1", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +dependencies = [ + "bytes", + "prost", + "tonic", +] + [[package]] name = "torrust-axum-health-check-api-server" version = "3.0.0-develop" @@ -4561,7 +5007,7 @@ dependencies = [ "hyper", "local-ip-address", "percent-encoding", - "rand 0.9.1", + "rand 0.9.2", "reqwest", "serde", "serde_bencode", @@ -4605,7 +5051,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "torrust-axum-server", "torrust-rest-tracker-api-client", @@ -4636,7 +5082,7 @@ dependencies = [ "hyper", "hyper-util", "pin-project-lite", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "torrust-server-lib", "torrust-tracker-configuration", @@ -4652,7 +5098,7 @@ dependencies = [ "hyper", "reqwest", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "url", "uuid", ] @@ -4680,7 +5126,7 @@ name = "torrust-server-lib" version = "3.0.0-develop" dependencies = [ "derive_more", - "rstest", + "rstest 0.25.0", "tokio", "torrust-tracker-primitives", "tower-http", @@ -4702,12 +5148,12 @@ dependencies = [ "clap", "local-ip-address", "mockall", - "rand 0.9.1", + "rand 0.9.2", "regex", "reqwest", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-axum-health-check-api-server", @@ -4743,7 +5189,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "torrust-tracker-configuration", "tracing", @@ -4771,8 +5217,8 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.12", - "toml", + "thiserror 2.0.17", + "toml 0.9.8", "torrust-tracker-located-error", "tracing", "tracing-subscriber", @@ -4784,8 +5230,8 @@ dependencies = [ name = "torrust-tracker-contrib-bencode" version = "3.0.0-develop" dependencies = [ - "criterion 0.6.0", - "thiserror 2.0.12", + "criterion 0.8.0", + "thiserror 2.0.17", ] [[package]] @@ -4801,7 +5247,7 @@ dependencies = [ name = "torrust-tracker-located-error" version = "3.0.0-develop" dependencies = [ - "thiserror 2.0.12", + "thiserror 2.0.17", "tracing", ] @@ -4814,10 +5260,10 @@ dependencies = [ "derive_more", "formatjson", "pretty_assertions", - "rstest", + "rstest 0.25.0", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", "torrust-tracker-primitives", "tracing", ] @@ -4830,11 +5276,11 @@ dependencies = [ "binascii", "bittorrent-primitives", "derive_more", - "rstest", + "rstest 0.25.0", "serde", "tdyne-peer-id", "tdyne-peer-id-registry", - "thiserror 2.0.12", + "thiserror 2.0.17", "torrust-tracker-configuration", "url", "zerocopy 0.7.35", @@ -4848,14 +5294,14 @@ dependencies = [ "async-std", "bittorrent-primitives", "chrono", - "criterion 0.6.0", + "criterion 0.8.0", "crossbeam-skiplist", "futures", "mockall", - "rand 0.9.1", - "rstest", + "rand 0.9.2", + "rstest 0.26.1", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-tracker-clock", @@ -4871,7 +5317,7 @@ dependencies = [ name = "torrust-tracker-test-helpers" version = "3.0.0-develop" dependencies = [ - "rand 0.9.1", + "rand 0.9.2", "torrust-tracker-configuration", "tracing", "tracing-subscriber", @@ -4884,12 +5330,12 @@ dependencies = [ "aquatic_udp_protocol", "async-std", "bittorrent-primitives", - "criterion 0.6.0", + "criterion 0.8.0", "crossbeam-skiplist", "dashmap", "futures", "parking_lot", - "rstest", + "rstest 0.26.1", "tokio", "torrust-tracker-clock", "torrust-tracker-configuration", @@ -4911,10 +5357,10 @@ dependencies = [ "futures-util", "local-ip-address", "mockall", - "rand 0.9.1", + "rand 0.9.2", "ringbuf", "serde", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-util", "torrust-server-lib", @@ -4939,9 +5385,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", + "indexmap 2.12.1", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -4949,12 +5398,12 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" dependencies = [ "async-compression", - "bitflags 2.9.1", + "bitflags", "bytes", "futures-core", "futures-util", @@ -4985,9 +5434,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "log", "pin-project-lite", @@ -4997,20 +5446,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.29" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", @@ -5039,9 +5488,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "nu-ansi-term", "serde", @@ -5073,9 +5522,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uncased" @@ -5088,9 +5537,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -5106,9 +5555,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -5122,11 +5571,39 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" +dependencies = [ + "base64 0.22.1", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "ureq-proto", + "utf-8", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +dependencies = [ + "base64 0.22.1", + "http", + "httparse", + "log", +] + [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -5134,6 +5611,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -5148,13 +5631,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", - "rand 0.9.1", + "rand 0.9.2", "wasm-bindgen", ] @@ -5166,9 +5649,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-bag" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" [[package]] name = "vcpkg" @@ -5208,45 +5691,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.102", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -5257,9 +5727,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5267,36 +5737,55 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.102", - "wasm-bindgen-backend", + "syn 2.0.111", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5315,11 +5804,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5330,9 +5819,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -5343,37 +5832,37 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "windows-link" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-registry" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ "windows-link", "windows-result", @@ -5382,18 +5871,18 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] @@ -5416,6 +5905,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5434,18 +5941,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -5456,9 +5964,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5468,9 +5976,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5480,9 +5988,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -5492,9 +6000,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5504,9 +6012,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5516,9 +6024,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5528,9 +6036,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5540,33 +6048,30 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -5579,9 +6084,9 @@ dependencies = [ [[package]] name = "xattr" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", "rustix", @@ -5595,11 +6100,10 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -5607,13 +6111,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", "synstructure", ] @@ -5629,11 +6133,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ - "zerocopy-derive 0.8.25", + "zerocopy-derive 0.8.31", ] [[package]] @@ -5644,18 +6148,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -5675,21 +6179,21 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -5698,9 +6202,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -5709,13 +6213,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.102", + "syn 2.0.111", ] [[package]] @@ -5738,9 +6242,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", From 00db8233574ccfc07f6de996da3fd9c3c3a19b67 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 2 Dec 2025 09:55:01 +0000 Subject: [PATCH 03/79] chore(deps): bump actions/checkout from 4 to 6 --- .github/workflows/container.yaml | 2 +- .github/workflows/coverage.yaml | 2 +- .github/workflows/deployment.yaml | 4 ++-- .github/workflows/generate_coverage_pr.yaml | 2 +- .github/workflows/labels.yaml | 2 +- .github/workflows/testing.yaml | 10 +++++----- .github/workflows/upload_coverage_pr.yaml | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index 9f51f3124..7416df71e 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -46,7 +46,7 @@ jobs: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: compose name: Compose diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index e10c5ac66..2c8d63d6c 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install LLVM tools run: sudo apt-get update && sudo apt-get install -y llvm diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml index 4e8fd579b..b544d1da2 100644 --- a/.github/workflows/deployment.yaml +++ b/.github/workflows/deployment.yaml @@ -17,7 +17,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain @@ -42,7 +42,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain diff --git a/.github/workflows/generate_coverage_pr.yaml b/.github/workflows/generate_coverage_pr.yaml index d1b241b9d..8363376b2 100644 --- a/.github/workflows/generate_coverage_pr.yaml +++ b/.github/workflows/generate_coverage_pr.yaml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Install LLVM tools run: sudo apt-get update && sudo apt-get install -y llvm diff --git a/.github/workflows/labels.yaml b/.github/workflows/labels.yaml index bb8283f30..a312c335f 100644 --- a/.github/workflows/labels.yaml +++ b/.github/workflows/labels.yaml @@ -25,7 +25,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: sync name: Apply Labels from File diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 671864fc9..c9328d890 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -15,7 +15,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain @@ -44,7 +44,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain @@ -96,7 +96,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain @@ -119,7 +119,7 @@ jobs: steps: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: setup name: Setup Toolchain @@ -173,7 +173,7 @@ jobs: - id: checkout name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - id: test name: Run E2E Tests diff --git a/.github/workflows/upload_coverage_pr.yaml b/.github/workflows/upload_coverage_pr.yaml index 1ed2f7bcc..a2a3c82a6 100644 --- a/.github/workflows/upload_coverage_pr.yaml +++ b/.github/workflows/upload_coverage_pr.yaml @@ -96,7 +96,7 @@ jobs: echo "override_commit=$(> "$GITHUB_OUTPUT" - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ steps.parse_previous_artifacts.outputs.override_commit || '' }} path: repo_root From 6757705ab631c4418eca9cb75b5bc24db1e84ee5 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 2 Dec 2025 09:57:21 +0000 Subject: [PATCH 04/79] chore(deps): bump actions/upload-artifact from 4 to 5 --- .github/workflows/generate_coverage_pr.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/generate_coverage_pr.yaml b/.github/workflows/generate_coverage_pr.yaml index 8363376b2..6942e276f 100644 --- a/.github/workflows/generate_coverage_pr.yaml +++ b/.github/workflows/generate_coverage_pr.yaml @@ -59,13 +59,13 @@ jobs: # Triggered sub-workflow is not able to detect the original commit/PR which is available # in this workflow. - name: Store PR number - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: pr_number path: pr_number.txt - name: Store commit SHA - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: commit_sha path: commit_sha.txt @@ -74,7 +74,7 @@ jobs: # is executed by a different workflow `upload_coverage.yml`. The reason for this # split is because `on.pull_request` workflows don't have access to secrets. - name: Store coverage report in artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: codecov_report path: ./codecov.json From 46b245004abea6bbf16afdadadbf9baa617797a0 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 2 Dec 2025 09:57:29 +0000 Subject: [PATCH 05/79] chore(deps): bump actions/github-script from 7 to 8 --- .github/workflows/upload_coverage_pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload_coverage_pr.yaml b/.github/workflows/upload_coverage_pr.yaml index a2a3c82a6..8b0006a6d 100644 --- a/.github/workflows/upload_coverage_pr.yaml +++ b/.github/workflows/upload_coverage_pr.yaml @@ -22,7 +22,7 @@ jobs: steps: - name: "Download existing coverage report" id: prepare_report - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | var fs = require('fs'); From 6cb7cdd932385a160c8b2da76842909a2277b04b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 2 Dec 2025 10:03:07 +0000 Subject: [PATCH 06/79] chore(deps): update Cargo dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tokio: 1.45.1 → 1.48.0 - reqwest: 0.12.20 → 0.12.24 - clap: 4.5.40 → 4.5.53 - tracing-subscriber: 0.3.19 → 0.3.22 - ringbuf: 0.4.4 → 0.4.8 - uuid: 1.18.1 → 1.19.0 - and other transitive dependencies Related dependabot PRs: - #1629 (tokio) - #1630 (reqwest) - #1623 (clap) - #1614 (tracing-subscriber) - #1604 (ringbuf) --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62d10c72f..952e1d8a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3484,9 +3484,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "101fec8d036f8d9d4a1e8ebf90d566d1d798f3b1aa379d2576a54a0d9acea5bd" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" dependencies = [ "bytes", "prost-derive", @@ -3494,9 +3494,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d93e596a829ebe00afa41c3a056e6308d6b8a4c7d869edf184e2c91b1ba564" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", "itertools 0.14.0", @@ -3507,9 +3507,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d7b7346e150de32340ae3390b8b3ffa37ad93ec31fb5dad86afe817619e4e7" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" dependencies = [ "prost", ] @@ -5631,9 +5631,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ "getrandom 0.3.4", "js-sys", From a2f9657ddb1d773d1067132dc0f7a2207b99c2c9 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:26:22 +0000 Subject: [PATCH 07/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 49 packages to latest compatible versions Updating async-compression v0.4.34 -> v0.4.36 Updating async-lock v3.4.1 -> v3.4.2 Updating axum v0.8.7 -> v0.8.8 Updating axum-extra v0.12.2 -> v0.12.3 Updating axum-server v0.7.3 -> v0.8.0 Updating bumpalo v3.19.0 -> v3.19.1 Updating cc v1.2.48 -> v1.2.50 Updating cmake v0.1.54 -> v0.1.57 Updating compression-codecs v0.4.33 -> v0.4.35 Adding convert_case v0.10.0 Updating criterion v0.8.0 -> v0.8.1 Updating criterion-plot v0.8.0 -> v0.8.1 Adding derive_builder v0.20.2 Adding derive_builder_core v0.20.2 Adding derive_builder_macro v0.20.2 Updating derive_more v2.0.1 -> v2.1.0 Updating derive_more-impl v2.0.1 -> v2.1.0 Updating ferroid v0.8.7 -> v0.8.8 Updating fs-err v3.2.0 -> v3.2.1 Adding getset v0.1.6 Updating hyper-util v0.1.18 -> v0.1.19 Updating icu_properties v2.1.1 -> v2.1.2 Updating icu_properties_data v2.1.1 -> v2.1.2 Updating itoa v1.0.15 -> v1.0.16 Updating libc v0.2.177 -> v0.2.178 Updating libredox v0.1.10 -> v0.1.11 Updating local-ip-address v0.6.5 -> v0.6.8 Updating log v0.4.28 -> v0.4.29 Updating mio v1.1.0 -> v1.1.1 Updating neli v0.6.5 -> v0.7.3 Updating neli-proc-macros v0.1.4 -> v0.2.2 Updating portable-atomic v1.11.1 -> v1.12.0 Adding redox_syscall v0.6.0 Updating reqwest v0.12.24 -> v0.12.26 Updating rustls-pki-types v1.13.1 -> v1.13.2 Updating ryu v1.0.20 -> v1.0.21 Updating serde_spanned v1.0.3 -> v1.0.4 Updating simd-adler32 v0.3.7 -> v0.3.8 Updating supports-hyperlinks v3.1.0 -> v3.2.0 Updating testcontainers v0.26.0 -> v0.26.2 Updating toml v0.9.8 -> v0.9.10+spec-1.1.0 Updating toml_datetime v0.7.3 -> v0.7.5+spec-1.1.0 Updating toml_edit v0.23.7 -> v0.23.10+spec-1.0.0 Updating toml_parser v1.0.4 -> v1.0.6+spec-1.1.0 Updating toml_writer v1.0.4 -> v1.0.6+spec-1.1.0 Updating tower-http v0.6.7 -> v0.6.8 Updating tracing v0.1.43 -> v0.1.44 Updating tracing-core v0.1.35 -> v0.1.36 Adding unicode-segmentation v1.12.0 Removing windows-sys v0.59.0 note: pass `--verbose` to see 7 unchanged dependencies behind latest ``` --- Cargo.lock | 278 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 952e1d8a6..da0910f48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,9 +236,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.34" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473" +checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" dependencies = [ "compression-codecs", "compression-core", @@ -297,9 +297,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener 5.4.1", "event-listener-strategy", @@ -395,9 +395,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ "axum-core", "axum-macros", @@ -459,9 +459,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfe9f610fe4e99cf0cfcd03ccf8c63c28c616fe714d80475ef731f3b13dd21b" +checksum = "6dfbd6109d91702d55fc56df06aae7ed85c465a7a451db6c0e54a4b9ca5983d1" dependencies = [ "axum", "axum-core", @@ -495,12 +495,13 @@ dependencies = [ [[package]] name = "axum-server" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ab4a3ec9ea8a657c72d99a03a824af695bd0fb5ec639ccbd9cd3543b41a5f9" +checksum = "b1df331683d982a0b9492b38127151e6453639cd34926eb9c07d4cd8c6d22bfc" dependencies = [ "arc-swap", "bytes", + "either", "fs-err", "http", "http-body", @@ -508,7 +509,6 @@ dependencies = [ "hyper-util", "pin-project-lite", "rustls", - "rustls-pemfile", "rustls-pki-types", "tokio", "tokio-rustls", @@ -948,9 +948,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytecheck" @@ -1018,9 +1018,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.48" +version = "1.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" dependencies = [ "find-msvc-tools", "jobserver", @@ -1151,9 +1151,9 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "cmake" -version = "0.1.54" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ "cc", ] @@ -1179,9 +1179,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.33" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad" +checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" dependencies = [ "brotli", "compression-core", @@ -1206,6 +1206,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1280,16 +1289,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" +checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" dependencies = [ "alloca", "anes", "cast", "ciborium", "clap", - "criterion-plot 0.8.0", + "criterion-plot 0.8.1", "itertools 0.13.0", "num-traits", "oorandom", @@ -1316,9 +1325,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" +checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" dependencies = [ "cast", "itertools 0.13.0", @@ -1500,23 +1509,56 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.111", +] + [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version", "syn 2.0.111", "unicode-xid", ] @@ -1680,9 +1722,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ferroid" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e9414a6ae93ef993ce40a1e02944f13d4508e2bf6f1ced1580ce6910f08253" +checksum = "ce161062fb044bd629c2393590efd47cab8d0241faf15704ffb0d47b7b4e4a35" dependencies = [ "portable-atomic", "rand 0.9.2", @@ -1854,9 +1896,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d91fd049c123429b018c47887d3f75a265540dd3c30ba9cb7bae9197edb03a" +checksum = "824f08d01d0f496b3eca4f001a13cf17690a6ee930043d20817f547455fd98f8" dependencies = [ "autocfg", "tokio", @@ -2009,6 +2051,18 @@ dependencies = [ "wasip2", ] +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "gimli" version = "0.32.3" @@ -2267,9 +2321,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "base64 0.22.1", "bytes", @@ -2378,9 +2432,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -2392,9 +2446,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -2553,9 +2607,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "jobserver" @@ -2594,9 +2648,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libloading" @@ -2616,13 +2670,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" dependencies = [ "bitflags", "libc", - "redox_syscall", + "redox_syscall 0.6.0", ] [[package]] @@ -2661,14 +2715,14 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "local-ip-address" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" +checksum = "0a60bf300a990b2d1ebdde4228e873e8e4da40d834adbf5265f3da1457ede652" dependencies = [ "libc", "neli", "thiserror 2.0.17", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2682,9 +2736,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" dependencies = [ "value-bag", ] @@ -2764,9 +2818,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", @@ -2918,27 +2972,31 @@ dependencies = [ [[package]] name = "neli" -version = "0.6.5" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" +checksum = "e23bebbf3e157c402c4d5ee113233e5e0610cc27453b2f07eefce649c7365dcc" dependencies = [ + "bitflags", "byteorder", + "derive_builder", + "getset", "libc", "log", "neli-proc-macros", + "parking_lot", ] [[package]] name = "neli-proc-macros" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" +checksum = "05d8d08c6e98f20a62417478ebf7be8e1425ec9acecc6f63e22da633f6b71609" dependencies = [ "either", "proc-macro2", "quote", "serde", - "syn 1.0.109", + "syn 2.0.111", ] [[package]] @@ -3156,7 +3214,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link", ] @@ -3356,9 +3414,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" [[package]] name = "portable-atomic-util" @@ -3435,7 +3493,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.7", + "toml_edit 0.23.10+spec-1.0.0", ] [[package]] @@ -3686,6 +3744,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5" +dependencies = [ + "bitflags", +] + [[package]] name = "ref-cast" version = "1.0.25" @@ -3752,9 +3819,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.24" +version = "0.12.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" dependencies = [ "base64 0.22.1", "bytes", @@ -4005,9 +4072,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "zeroize", ] @@ -4031,9 +4098,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "same-file" @@ -4256,9 +4323,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ "serde_core", ] @@ -4354,9 +4421,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simdutf8" @@ -4470,9 +4537,9 @@ dependencies = [ [[package]] name = "supports-hyperlinks" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" [[package]] name = "supports-unicode" @@ -4606,9 +4673,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.26.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a347cac4368ba4f1871743adb27dc14829024d26b1763572404726b0b9943eb8" +checksum = "1483605f58b2fff80d786eb56a0b6b4e8b1e5423fbc9ec2e3e562fa2040d6f27" dependencies = [ "astral-tokio-tar", "async-trait", @@ -4844,14 +4911,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.8" +version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ "indexmap 2.12.1", "serde_core", - "serde_spanned 1.0.3", - "toml_datetime 0.7.3", + "serde_spanned 1.0.4", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", "winnow", @@ -4868,9 +4935,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] @@ -4891,21 +4958,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.7" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap 2.12.1", - "toml_datetime 0.7.3", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -4918,9 +4985,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.4" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tonic" @@ -5218,7 +5285,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror 2.0.17", - "toml 0.9.8", + "toml 0.9.10+spec-1.1.0", "torrust-tracker-located-error", "tracing", "tracing-subscriber", @@ -5230,7 +5297,7 @@ dependencies = [ name = "torrust-tracker-contrib-bencode" version = "3.0.0-develop" dependencies = [ - "criterion 0.8.0", + "criterion 0.8.1", "thiserror 2.0.17", ] @@ -5294,7 +5361,7 @@ dependencies = [ "async-std", "bittorrent-primitives", "chrono", - "criterion 0.8.0", + "criterion 0.8.1", "crossbeam-skiplist", "futures", "mockall", @@ -5330,7 +5397,7 @@ dependencies = [ "aquatic_udp_protocol", "async-std", "bittorrent-primitives", - "criterion 0.8.0", + "criterion 0.8.1", "crossbeam-skiplist", "dashmap", "futures", @@ -5398,9 +5465,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", "bitflags", @@ -5434,9 +5501,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -5457,9 +5524,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -5547,6 +5614,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.1.14" @@ -5896,15 +5969,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" From 4c16227bdaa03c236cc597b93dc49563224e0afe Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:35:13 +0000 Subject: [PATCH 08/79] fix: E0107 - missing generics for struct axum_server::Server in from_tcp_with_timeouts error[E0107]: missing generics for struct `axum_server::Server` --> packages/axum-server/src/custom_axum_server.rs:44:55 | 44 | pub fn from_tcp_with_timeouts(socket: TcpListener) -> Server { | ^^^^^^ expected at least 1 generic argument Added SocketAddr generic parameter to Server return type and Address trait bound to add_timeouts function. --- packages/axum-server/src/custom_axum_server.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index 5705ef24e..fccaf54dc 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -18,7 +18,7 @@ //! If you want to know more about Axum and timeouts see . use std::future::Ready; use std::io::ErrorKind; -use std::net::TcpListener; +use std::net::{SocketAddr, TcpListener}; use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; @@ -41,7 +41,7 @@ const HTTP2_KEEP_ALIVE_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(5); #[must_use] -pub fn from_tcp_with_timeouts(socket: TcpListener) -> Server { +pub fn from_tcp_with_timeouts(socket: TcpListener) -> Server { add_timeouts(axum_server::from_tcp(socket)) } @@ -50,7 +50,7 @@ pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> add_timeouts(axum_server::from_tcp_rustls(socket, tls)) } -fn add_timeouts(mut server: Server) -> Server { +fn add_timeouts(mut server: Server) -> Server { server.http_builder().http1().timer(TokioTimer::new()); server.http_builder().http2().timer(TokioTimer::new()); From 51452a8b2a7aee04822e90651179c2b0a8bb031f Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:38:42 +0000 Subject: [PATCH 09/79] fix: E0277 and E0308 - RustlsAcceptor trait bounds and type mismatch in from_tcp_rustls_with_timeouts error[E0277]: the trait bound `RustlsAcceptor: Address` is not satisfied --> packages/axum-server/src/custom_axum_server.rs:49:81 | 49 | ... tls: RustlsConfig) -> Server { | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound error[E0308]: mismatched types --> packages/axum-server/src/custom_axum_server.rs:50:18 | 50 | add_timeouts(axum_server::from_tcp_rustls(socket, tls)) | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Server`, found `Result, ...>` Changed return type to Result, std::io::Error> and used map to apply add_timeouts to the Result value. --- packages/axum-server/src/custom_axum_server.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index fccaf54dc..39a2271d6 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -36,6 +36,8 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; use tokio::time::{Instant, Sleep}; use tower::Service; +type RustlsServerResult = Result, std::io::Error>; + const HTTP1_HEADER_READ_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(5); @@ -46,8 +48,8 @@ pub fn from_tcp_with_timeouts(socket: TcpListener) -> Server { } #[must_use] -pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> Server { - add_timeouts(axum_server::from_tcp_rustls(socket, tls)) +pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> RustlsServerResult { + axum_server::from_tcp_rustls(socket, tls).map(add_timeouts) } fn add_timeouts(mut server: Server) -> Server { From 74d5c8b9f0520077e8ec3baf84423808f771a285 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:39:14 +0000 Subject: [PATCH 10/79] fix: E0308 - mismatched types, from_tcp returns Result in from_tcp_with_timeouts error[E0308]: mismatched types --> packages/axum-server/src/custom_axum_server.rs:47:18 | 47 | add_timeouts(axum_server::from_tcp(socket)) | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Server`, found `Result, Error>` Changed return type to Result, std::io::Error> and used map to apply add_timeouts to the Result value. --- packages/axum-server/src/custom_axum_server.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index 39a2271d6..b7f1d664e 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -37,14 +37,15 @@ use tokio::time::{Instant, Sleep}; use tower::Service; type RustlsServerResult = Result, std::io::Error>; +type ServerResult = Result, std::io::Error>; const HTTP1_HEADER_READ_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(5); #[must_use] -pub fn from_tcp_with_timeouts(socket: TcpListener) -> Server { - add_timeouts(axum_server::from_tcp(socket)) +pub fn from_tcp_with_timeouts(socket: TcpListener) -> ServerResult { + axum_server::from_tcp(socket).map(add_timeouts) } #[must_use] From cd83cfd9491cc9369921d560467d5cbfec917d02 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:39:45 +0000 Subject: [PATCH 11/79] fix: E0631 - type mismatch in add_timeouts function arguments for acceptor type error[E0631]: type mismatch in function arguments --> packages/axum-server/src/custom_axum_server.rs:53:51 | 53 | axum_server::from_tcp_rustls(socket, tls).map(add_timeouts) | --- ^^^^^^^^^^^^ expected due to this | = note: expected function signature `fn(Server<_, RustlsAcceptor>) -> _` found function signature `fn(Server<_, DefaultAcceptor>) -> _` Made add_timeouts generic over both Address and Acceptor types to work with both DefaultAcceptor and RustlsAcceptor. --- packages/axum-server/src/custom_axum_server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index b7f1d664e..e3567bad4 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -53,7 +53,7 @@ pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> axum_server::from_tcp_rustls(socket, tls).map(add_timeouts) } -fn add_timeouts(mut server: Server) -> Server { +fn add_timeouts(mut server: Server) -> Server { server.http_builder().http1().timer(TokioTimer::new()); server.http_builder().http2().timer(TokioTimer::new()); From 612f7f1f07e69ce3e0fdeb3c8b264f46917aa06e Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:40:10 +0000 Subject: [PATCH 12/79] fix: E0107 - missing generics for struct axum_server::Handle in signals.rs error[E0107]: missing generics for struct `axum_server::Handle` --> packages/axum-server/src/signals.rs:10:26 | 10 | handle: axum_server::Handle, | ^^^^^^ expected 1 generic argument Added SocketAddr generic parameter to Handle type in graceful_shutdown function signature. --- packages/axum-server/src/signals.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/axum-server/src/signals.rs b/packages/axum-server/src/signals.rs index 268ff79fa..360879e32 100644 --- a/packages/axum-server/src/signals.rs +++ b/packages/axum-server/src/signals.rs @@ -7,7 +7,7 @@ use tracing::instrument; #[instrument(skip(handle, rx_halt, message))] pub async fn graceful_shutdown( - handle: axum_server::Handle, + handle: axum_server::Handle, rx_halt: tokio::sync::oneshot::Receiver, message: String, address: SocketAddr, From 37793ce42e19ab922ad70948631d8f26ecad9213 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:41:05 +0000 Subject: [PATCH 13/79] fix: clippy::uninlined_format_args - variables can be used directly in format! string --> console/tracker-client/src/console/clients/udp/app.rs:178:24 | | __________________^ 179 | | ... "invalid address format: \`{}\`. Expected format is host:port", 180 | | ... tracker_socket_addr_str 181 | | ... )); | |_______^ --> console/tracker-client/src/console/clients/udp/app.rs:199:13 | 199 | ...rr(anyhow::anyhow!("DNS resolution failed for \`{}\`", tracker_socket_addr_str)) Changed format strings to use inline variable interpolation instead of positional arguments. --- console/tracker-client/src/console/clients/udp/app.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/console/tracker-client/src/console/clients/udp/app.rs b/console/tracker-client/src/console/clients/udp/app.rs index a2736c365..527f46e78 100644 --- a/console/tracker-client/src/console/clients/udp/app.rs +++ b/console/tracker-client/src/console/clients/udp/app.rs @@ -176,8 +176,7 @@ fn parse_socket_addr(tracker_socket_addr_str: &str) -> anyhow::Result anyhow::Result = resolved_addr.to_socket_addrs()?.collect(); if socket_addrs.is_empty() { - Err(anyhow::anyhow!("DNS resolution failed for `{}`", tracker_socket_addr_str)) + Err(anyhow::anyhow!("DNS resolution failed for `{tracker_socket_addr_str}`")) } else { Ok(socket_addrs[0]) } From f0678be9cf46a549ebd811800754f9b24b2dab7b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:41:49 +0000 Subject: [PATCH 14/79] fix: clippy::missing_errors_doc and clippy::double_must_use for from_tcp_with_timeouts error: docs for function returning `Result` missing `# Errors` section --> packages/axum-server/src/custom_axum_server.rs:47:1 | 47 | pub fn from_tcp_with_timeouts(socket: TcpListener) -> ServerResult { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> packages/axum-server/src/custom_axum_server.rs:47:1 | 47 | pub fn from_tcp_with_timeouts(socket: TcpListener) -> ServerResult { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Added documentation with Errors section and removed #[must_use] attribute since Result type already has it. --- packages/axum-server/src/custom_axum_server.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index e3567bad4..f332c9288 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -43,7 +43,11 @@ const HTTP1_HEADER_READ_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_TIMEOUT: Duration = Duration::from_secs(5); const HTTP2_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(5); -#[must_use] +/// Creates an Axum server from a TCP listener with configured timeouts. +/// +/// # Errors +/// +/// Returns an error if the server cannot be created from the TCP socket. pub fn from_tcp_with_timeouts(socket: TcpListener) -> ServerResult { axum_server::from_tcp(socket).map(add_timeouts) } From ea001980306165b863393cc3b0ef1f28c0b61cf9 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:42:12 +0000 Subject: [PATCH 15/79] fix: clippy::missing_errors_doc and clippy::double_must_use for from_tcp_rustls_with_timeouts error: docs for function returning `Result` missing `# Errors` section --> packages/axum-server/src/custom_axum_server.rs:52:1 | 52 | pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> RustlsServerResult { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> packages/axum-server/src/custom_axum_server.rs:52:1 | 52 | pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> RustlsServerResult { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Added documentation with Errors section and removed #[must_use] attribute since Result type already has it. --- packages/axum-server/src/custom_axum_server.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/axum-server/src/custom_axum_server.rs b/packages/axum-server/src/custom_axum_server.rs index f332c9288..0328198ec 100644 --- a/packages/axum-server/src/custom_axum_server.rs +++ b/packages/axum-server/src/custom_axum_server.rs @@ -52,7 +52,11 @@ pub fn from_tcp_with_timeouts(socket: TcpListener) -> ServerResult { axum_server::from_tcp(socket).map(add_timeouts) } -#[must_use] +/// Creates an Axum server from a TCP listener with TLS and configured timeouts. +/// +/// # Errors +/// +/// Returns an error if the server cannot be created from the TCP socket or if TLS configuration fails. pub fn from_tcp_rustls_with_timeouts(socket: TcpListener, tls: RustlsConfig) -> RustlsServerResult { axum_server::from_tcp_rustls(socket, tls).map(add_timeouts) } From a217bb924a427e281f8df91b7f0a299627293a78 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:43:28 +0000 Subject: [PATCH 16/79] fix: E0599 - no method named handle found for Result in health-check-api-server error[E0599]: no method named `handle` found for enum `std::result::Result` in the current scope --> packages/axum-health-check-api-server/src/server.rs:120:10 | 119 | let running = axum_server::from_tcp(socket) | ___________________- 120 | | .handle(handle) | |_________-^^^^^^ Added expect() to unwrap Result before calling handle() method since from_tcp now returns Result. --- packages/axum-health-check-api-server/src/server.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/axum-health-check-api-server/src/server.rs b/packages/axum-health-check-api-server/src/server.rs index 3eeb1b054..c261f6af8 100644 --- a/packages/axum-health-check-api-server/src/server.rs +++ b/packages/axum-health-check-api-server/src/server.rs @@ -117,6 +117,7 @@ pub fn start( )); let running = axum_server::from_tcp(socket) + .expect("Failed to create server from TCP socket") .handle(handle) .serve(router.into_make_service_with_connect_info::()); From 054843477e3c73d132b7ca71dee208e3bec65dd8 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:44:09 +0000 Subject: [PATCH 17/79] fix: E0599 and E0282 - no method named handle found for Result in axum-http-tracker-server error[E0599]: no method named `handle` found for enum `std::result::Result` in the current scope --> packages/axum-http-tracker-server/src/server.rs:77:22 | 76 | ... Some(tls) => custom_axum_server::from_tcp_rustls_with_timeouts(socket, tls) | ____________________- 77 | | ... .handle(handle) | |___________-^^^^^^ error[E0599]: no method named `handle` found for enum `std::result::Result` in the current scope --> packages/axum-http-tracker-server/src/server.rs:85:22 | 84 | None => custom_axum_server::from_tcp_with_timeouts(socket) | _________________________- 85 | | .handle(handle) | |_____________________-^^^^^^ Added expect() calls to unwrap Result before calling handle() method for both TLS and non-TLS cases. --- packages/axum-http-tracker-server/src/server.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/axum-http-tracker-server/src/server.rs b/packages/axum-http-tracker-server/src/server.rs index 2b43be0a9..4b7c15de8 100644 --- a/packages/axum-http-tracker-server/src/server.rs +++ b/packages/axum-http-tracker-server/src/server.rs @@ -74,6 +74,7 @@ impl Launcher { let running = Box::pin(async { match tls { Some(tls) => custom_axum_server::from_tcp_rustls_with_timeouts(socket, tls) + .expect("Failed to create server from TCP socket with TLS") .handle(handle) // The TimeoutAcceptor is commented because TSL does not work with it. // See: https://github.com/torrust/torrust-index/issues/204#issuecomment-2115529214 @@ -82,6 +83,7 @@ impl Launcher { .await .expect("Axum server crashed."), None => custom_axum_server::from_tcp_with_timeouts(socket) + .expect("Failed to create server from TCP socket") .handle(handle) .acceptor(TimeoutAcceptor) .serve(app.into_make_service_with_connect_info::()) From 02e43394e2d30370ae8214b2d513c947773123b5 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:45:06 +0000 Subject: [PATCH 18/79] fix: E0599 and E0282 - no method named handle found for Result in axum-rest-tracker-api-server error[E0599]: no method named `handle` found for enum `std::result::Result` in the current scope --> packages/axum-rest-tracker-api-server/src/server.rs:272:22 | 271 | ... Some(tls) => custom_axum_server::from_tcp_rustls_with_timeouts(socket, tls) | ____________________- 272 | | ... .handle(handle) | |___________-^^^^^^ error[E0599]: no method named `handle` found for enum `std::result::Result` in the current scope --> packages/axum-rest-tracker-api-server/src/server.rs:280:22 | 279 | None => custom_axum_server::from_tcp_with_timeouts(socket) | _________________________- 280 | | .handle(handle) | |_____________________-^^^^^^ Added expect() calls to unwrap Result before calling handle() method for both TLS and non-TLS cases. --- packages/axum-rest-tracker-api-server/src/server.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/axum-rest-tracker-api-server/src/server.rs b/packages/axum-rest-tracker-api-server/src/server.rs index b358345fb..a867ecfcf 100644 --- a/packages/axum-rest-tracker-api-server/src/server.rs +++ b/packages/axum-rest-tracker-api-server/src/server.rs @@ -269,6 +269,7 @@ impl Launcher { let running = Box::pin(async { match tls { Some(tls) => custom_axum_server::from_tcp_rustls_with_timeouts(socket, tls) + .expect("Failed to create server from TCP socket with TLS") .handle(handle) // The TimeoutAcceptor is commented because TSL does not work with it. // See: https://github.com/torrust/torrust-index/issues/204#issuecomment-2115529214 @@ -277,6 +278,7 @@ impl Launcher { .await .expect("Axum server for tracker API crashed."), None => custom_axum_server::from_tcp_with_timeouts(socket) + .expect("Failed to create server from TCP socket") .handle(handle) .acceptor(TimeoutAcceptor) .serve(router.into_make_service_with_connect_info::()) From a62eb146fae7de0edb671c65e99d108ca18db2e5 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 08:51:04 +0000 Subject: [PATCH 19/79] fix: runtime panic - Registering a blocking socket with tokio runtime is unsupported thread 'tokio-runtime-worker' panicked at /home/josecelano/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-server-0.8.0/src/server.rs:70:30: Registering a blocking socket with the tokio runtime is unsupported. If you wish to do anyways, please add `--cfg tokio_allow_from_blocking_fd` to your RUSTFLAGS. See github.com/tokio-rs/tokio/issues/7172 for details. Set std::net::TcpListener instances to non-blocking mode using set_nonblocking(true) before passing them to axum-server to avoid runtime panics when registering with tokio runtime. This is required since axum-server 0.8.0 and tokio v1.44.0 which added debug assertions to prevent blocking sockets from being registered with the tokio runtime. --- packages/axum-health-check-api-server/src/server.rs | 3 +++ packages/axum-http-tracker-server/src/server.rs | 3 +++ packages/axum-rest-tracker-api-server/src/server.rs | 1 + 3 files changed, 7 insertions(+) diff --git a/packages/axum-health-check-api-server/src/server.rs b/packages/axum-health-check-api-server/src/server.rs index c261f6af8..a371f146e 100644 --- a/packages/axum-health-check-api-server/src/server.rs +++ b/packages/axum-health-check-api-server/src/server.rs @@ -101,6 +101,9 @@ pub fn start( .layer(SetRequestIdLayer::x_request_id(MakeRequestUuid)); let socket = std::net::TcpListener::bind(bind_to).expect("Could not bind tcp_listener to address."); + socket + .set_nonblocking(true) + .expect("Failed to set socket to non-blocking mode"); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); let protocol = Protocol::HTTP; // The health check API only supports HTTP directly now. Use a reverse proxy for HTTPS. let service_binding = ServiceBinding::new(protocol.clone(), address).expect("Service binding creation failed"); diff --git a/packages/axum-http-tracker-server/src/server.rs b/packages/axum-http-tracker-server/src/server.rs index 4b7c15de8..69f9cb72e 100644 --- a/packages/axum-http-tracker-server/src/server.rs +++ b/packages/axum-http-tracker-server/src/server.rs @@ -52,6 +52,9 @@ impl Launcher { rx_halt: Receiver, ) -> BoxFuture<'static, ()> { let socket = std::net::TcpListener::bind(self.bind_to).expect("Could not bind tcp_listener to address."); + socket + .set_nonblocking(true) + .expect("Failed to set socket to non-blocking mode"); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); let handle = Handle::new(); diff --git a/packages/axum-rest-tracker-api-server/src/server.rs b/packages/axum-rest-tracker-api-server/src/server.rs index a867ecfcf..32c1051e1 100644 --- a/packages/axum-rest-tracker-api-server/src/server.rs +++ b/packages/axum-rest-tracker-api-server/src/server.rs @@ -247,6 +247,7 @@ impl Launcher { rx_halt: Receiver, ) -> BoxFuture<'static, ()> { let socket = std::net::TcpListener::bind(self.bind_to).expect("Could not bind tcp_listener to address."); + socket.set_nonblocking(true).expect("Failed to set socket to non-blocking mode"); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); let router = router(http_api_container, access_tokens, address); From eccab24403fb95be99f3be3bd05875d2e2ac1916 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 09:07:47 +0000 Subject: [PATCH 20/79] style: apply cargo fmt formatting to axum-rest-tracker-api-server Format set_nonblocking call to use multi-line formatting per rustfmt conventions. --- packages/axum-rest-tracker-api-server/src/server.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/axum-rest-tracker-api-server/src/server.rs b/packages/axum-rest-tracker-api-server/src/server.rs index 32c1051e1..05adeae8a 100644 --- a/packages/axum-rest-tracker-api-server/src/server.rs +++ b/packages/axum-rest-tracker-api-server/src/server.rs @@ -247,7 +247,9 @@ impl Launcher { rx_halt: Receiver, ) -> BoxFuture<'static, ()> { let socket = std::net::TcpListener::bind(self.bind_to).expect("Could not bind tcp_listener to address."); - socket.set_nonblocking(true).expect("Failed to set socket to non-blocking mode"); + socket + .set_nonblocking(true) + .expect("Failed to set socket to non-blocking mode"); let address = socket.local_addr().expect("Could not get local_addr from tcp_listener."); let router = router(http_api_container, access_tokens, address); From 38ed4cbc074c7322ba6b898bf424ba935bb419e3 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 22 Dec 2025 16:38:41 +0000 Subject: [PATCH 21/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 4 packages to latest compatible versions Updating derive_more v2.1.0 -> v2.1.1 Updating derive_more-impl v2.1.0 -> v2.1.1 Updating reqwest v0.12.26 -> v0.12.27 Updating serde_json v1.0.145 -> v1.0.146 note: pass `--verbose` to see 7 unchanged dependencies behind latest ``` --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da0910f48..3bdf93e00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1542,18 +1542,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -3819,9 +3819,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "8e893f6bece5953520ddbb3f8f46f3ef36dd1fef4ee9b087c4b4a725fd5d10e4" dependencies = [ "base64 0.22.1", "bytes", @@ -4278,9 +4278,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" dependencies = [ "indexmap 2.12.1", "itoa", From 767bb5c2ec9e3042ad28d0d36c7a8e1071385889 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 23 Dec 2025 08:58:13 +0000 Subject: [PATCH 22/79] fix: [#1628] upgrade to Debian 13 (Trixie) to resolve security vulnerabilities - Update base images from Debian 12 (bookworm) to Debian 13 (trixie) - Update builder: rust:bookworm -> rust:trixie - Update tester: rust:slim-bookworm -> rust:slim-trixie - Update GCC: gcc:bookworm -> gcc:trixie - Update runtime: gcr.io/distroless/cc-debian12:debug -> gcr.io/distroless/cc-debian13:debug This resolves all 5 security vulnerabilities (1 CRITICAL, 4 HIGH): - CVE-2019-1010022 (CRITICAL): glibc stack guard protection bypass - CVE-2018-20796 (HIGH): glibc uncontrolled recursion - CVE-2019-1010023 (HIGH): glibc ldd malicious ELF code execution - CVE-2019-9192 (HIGH): glibc uncontrolled recursion - CVE-2023-0286 (HIGH): OpenSSL X.400 address type confusion Trivy scan results: - Before: Total 5 (CRITICAL: 1, HIGH: 4) - After: Total 0 (CRITICAL: 0, HIGH: 0) Container tested and verified working with health checks passing. --- Containerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Containerfile b/Containerfile index 263053390..e926a5202 100644 --- a/Containerfile +++ b/Containerfile @@ -3,13 +3,13 @@ # Torrust Tracker ## Builder Image -FROM docker.io/library/rust:bookworm AS chef +FROM docker.io/library/rust:trixie AS chef WORKDIR /tmp RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash RUN cargo binstall --no-confirm cargo-chef cargo-nextest ## Tester Image -FROM docker.io/library/rust:slim-bookworm AS tester +FROM docker.io/library/rust:slim-trixie AS tester WORKDIR /tmp RUN apt-get update; apt-get install -y curl sqlite3; apt-get autoclean @@ -21,7 +21,7 @@ RUN mkdir -p /app/share/torrust/default/database/; \ sqlite3 /app/share/torrust/default/database/tracker.sqlite3.db "VACUUM;" ## Su Exe Compile -FROM docker.io/library/gcc:bookworm AS gcc +FROM docker.io/library/gcc:trixie AS gcc COPY ./contrib/dev-tools/su-exec/ /usr/local/src/su-exec/ RUN cc -Wall -Werror -g /usr/local/src/su-exec/su-exec.c -o /usr/local/bin/su-exec; chmod +x /usr/local/bin/su-exec @@ -91,7 +91,7 @@ RUN chown -R root:root /app; chmod -R u=rw,go=r,a+X /app; chmod -R a+x /app/bin ## Runtime -FROM gcr.io/distroless/cc-debian12:debug AS runtime +FROM gcr.io/distroless/cc-debian13:debug AS runtime RUN ["/busybox/cp", "-sp", "/busybox/sh","/busybox/cat","/busybox/ls","/busybox/env", "/bin/"] COPY --from=gcc --chmod=0555 /usr/local/bin/su-exec /bin/su-exec From 300be03c24aa769d55b8415d310c2e032cff59ce Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 23 Dec 2025 09:50:17 +0000 Subject: [PATCH 23/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 2 packages to latest compatible versions Updating reqwest v0.12.27 -> v0.12.28 Updating rustix v1.1.2 -> v1.1.3 note: pass `--verbose` to see 7 unchanged dependencies behind latest ``` --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bdf93e00..d0478573b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3819,9 +3819,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.27" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e893f6bece5953520ddbb3f8f46f3ef36dd1fef4ee9b087c4b4a725fd5d10e4" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -4023,9 +4023,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", From c9c027dfe96fbb4b5558f6519cb936d9ff9f5f1d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 23 Dec 2025 09:58:13 +0000 Subject: [PATCH 24/79] chore(deps): bump actions/upload-artifact from 5 to 6 Bumps actions/upload-artifact from 5 to 6. This update includes: - Node.js 24 runtime support - Requires Actions Runner version 2.327.1 or later - Fixes punycode deprecation warnings --- .github/workflows/generate_coverage_pr.yaml | 6 +++--- cSpell.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/generate_coverage_pr.yaml b/.github/workflows/generate_coverage_pr.yaml index 6942e276f..f762207cf 100644 --- a/.github/workflows/generate_coverage_pr.yaml +++ b/.github/workflows/generate_coverage_pr.yaml @@ -59,13 +59,13 @@ jobs: # Triggered sub-workflow is not able to detect the original commit/PR which is available # in this workflow. - name: Store PR number - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: pr_number path: pr_number.txt - name: Store commit SHA - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: commit_sha path: commit_sha.txt @@ -74,7 +74,7 @@ jobs: # is executed by a different workflow `upload_coverage.yml`. The reason for this # split is because `on.pull_request` workflows don't have access to secrets. - name: Store coverage report in artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: codecov_report path: ./codecov.json diff --git a/cSpell.json b/cSpell.json index 76939c199..81421e050 100644 --- a/cSpell.json +++ b/cSpell.json @@ -32,6 +32,7 @@ "canonicalized", "certbot", "chrono", + "Cinstrument", "ciphertext", "clippy", "cloneable", From 8dde9c3e1b217ebd974670f5d309c590e6dba105 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 26 Jan 2026 12:41:33 +0000 Subject: [PATCH 25/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 109 packages to latest compatible versions Updating arc-swap v1.7.1 -> v1.8.0 Updating async-compression v0.4.36 -> v0.4.37 Adding aws-lc-rs v1.15.4 Adding aws-lc-sys v0.37.0 Updating axum-core v0.5.5 -> v0.5.6 Updating axum-extra v0.12.3 -> v0.12.5 Updating bigdecimal v0.4.9 -> v0.4.10 Updating cc v1.2.50 -> v1.2.54 Adding cesu8 v1.1.0 Updating chrono v0.4.42 -> v0.4.43 Updating clap v4.5.53 -> v4.5.54 Updating clap_builder v4.5.53 -> v4.5.54 Updating clap_lex v0.7.6 -> v0.7.7 Adding combine v4.6.7 Updating compression-codecs v0.4.35 -> v0.4.36 Adding dunce v1.0.5 Updating ferroid v0.8.8 -> v0.8.9 Updating filetime v0.2.26 -> v0.2.27 Updating find-msvc-tools v0.1.5 -> v0.1.8 Updating flate2 v1.1.5 -> v1.1.8 Adding foldhash v0.2.0 Updating fs-err v3.2.1 -> v3.2.2 Adding fs_extra v1.3.0 Updating getrandom v0.2.16 -> v0.2.17 Updating h2 v0.4.12 -> v0.4.13 Updating hashlink v0.10.0 -> v0.11.0 Removing hyper-tls v0.6.0 Updating indexmap v2.12.1 -> v2.13.0 Updating iri-string v0.7.9 -> v0.7.10 Updating itoa v1.0.16 -> v1.0.17 Adding jni v0.21.1 Adding jni-sys v0.3.0 Updating js-sys v0.3.83 -> v0.3.85 Updating libc v0.2.178 -> v0.2.180 Updating libm v0.2.15 -> v0.2.16 Updating libredox v0.1.11 -> v0.1.12 Updating libsqlite3-sys v0.35.0 -> v0.36.0 Updating local-ip-address v0.6.8 -> v0.6.9 Adding lru-slab v0.1.2 Updating num-conv v0.1.0 -> v0.2.0 Adding openssl-probe v0.2.1 Updating portable-atomic v1.12.0 -> v1.13.0 Updating proc-macro2 v1.0.103 -> v1.0.106 Updating prost v0.14.1 -> v0.14.3 Updating prost-derive v0.14.1 -> v0.14.3 Updating prost-types v0.14.1 -> v0.14.3 Adding quinn v0.11.9 Adding quinn-proto v0.11.13 Adding quinn-udp v0.5.14 Updating quote v1.0.42 -> v1.0.44 Updating r2d2_sqlite v0.31.0 -> v0.32.0 Updating rand_core v0.9.3 -> v0.9.5 Updating redox_syscall v0.6.0 -> v0.7.0 Updating reqwest v0.12.28 -> v0.13.1 Updating rkyv v0.7.45 -> v0.7.46 Updating rkyv_derive v0.7.45 -> v0.7.46 Adding rsqlite-vfs v0.1.0 Updating rusqlite v0.37.0 -> v0.38.0 Updating rust_decimal v1.39.0 -> v1.40.0 Updating rustc-demangle v0.1.26 -> v0.1.27 Updating rustls v0.23.35 -> v0.23.36 Updating rustls-native-certs v0.8.2 -> v0.8.3 Updating rustls-pki-types v1.13.2 -> v1.14.0 Adding rustls-platform-verifier v0.6.2 Adding rustls-platform-verifier-android v0.1.1 Updating rustls-webpki v0.103.8 -> v0.103.9 Updating ryu v1.0.21 -> v1.0.22 Updating schemars v1.1.0 -> v1.2.0 Updating serde_json v1.0.146 -> v1.0.149 Updating signal-hook-registry v1.4.7 -> v1.4.8 Updating socket2 v0.6.1 -> v0.6.2 Adding sqlite-wasm-rs v0.5.2 Updating subprocess v0.2.9 -> v0.2.13 Updating syn v2.0.111 -> v2.0.114 Updating tempfile v3.23.0 -> v3.24.0 Updating testcontainers v0.26.2 -> v0.26.3 Updating thiserror v2.0.17 -> v2.0.18 Updating thiserror-impl v2.0.17 -> v2.0.18 Updating time v0.3.44 -> v0.3.46 Updating time-core v0.1.6 -> v0.1.8 Updating time-macros v0.2.24 -> v0.2.26 Updating tokio v1.48.0 -> v1.49.0 Removing tokio-native-tls v0.3.1 Updating tokio-stream v0.1.17 -> v0.1.18 Updating tokio-util v0.7.17 -> v0.7.18 Updating toml v0.9.10+spec-1.1.0 -> v0.9.11+spec-1.1.0 Updating tower v0.5.2 -> v0.5.3 Updating url v2.5.7 -> v2.5.8 Updating uuid v1.19.0 -> v1.20.0 Updating wasip2 v1.0.1+wasi-0.2.4 -> v1.0.2+wasi-0.2.9 Updating wasm-bindgen v0.2.106 -> v0.2.108 Updating wasm-bindgen-futures v0.4.56 -> v0.4.58 Updating wasm-bindgen-macro v0.2.106 -> v0.2.108 Updating wasm-bindgen-macro-support v0.2.106 -> v0.2.108 Updating wasm-bindgen-shared v0.2.106 -> v0.2.108 Updating web-sys v0.3.83 -> v0.3.85 Adding webpki-root-certs v1.0.5 Updating webpki-roots v1.0.4 -> v1.0.5 Adding windows-sys v0.45.0 Adding windows-targets v0.42.2 Adding windows_aarch64_gnullvm v0.42.2 Adding windows_aarch64_msvc v0.42.2 Adding windows_i686_gnu v0.42.2 Adding windows_i686_msvc v0.42.2 Adding windows_x86_64_gnu v0.42.2 Adding windows_x86_64_gnullvm v0.42.2 Adding windows_x86_64_msvc v0.42.2 Updating wit-bindgen v0.46.0 -> v0.51.0 Updating zerocopy v0.8.31 -> v0.8.34 Updating zerocopy-derive v0.8.31 -> v0.8.34 Adding zmij v1.0.17 note: pass `--verbose` to see 7 unchanged dependencies behind latest ``` --- Cargo.lock | 850 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 557 insertions(+), 293 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0478573b..146da3a18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "version_check", ] @@ -175,9 +175,12 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +dependencies = [ + "rustversion", +] [[package]] name = "arrayvec" @@ -236,13 +239,12 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" +checksum = "d10e4f991a553474232bc0a31799f6d24b034a84c0971d80d2e2f78b2e576e40" dependencies = [ "compression-codecs", "compression-core", - "futures-core", "pin-project-lite", "tokio", ] @@ -352,7 +354,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -369,7 +371,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -393,6 +395,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.8.8" @@ -440,9 +464,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -459,9 +483,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dfbd6109d91702d55fc56df06aae7ed85c465a7a451db6c0e54a4b9ca5983d1" +checksum = "fef252edff26ddba56bbcdf2ee3307b8129acb86f5749b68990c168a6fcc9c76" dependencies = [ "axum", "axum-core", @@ -490,7 +514,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -553,9 +577,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bigdecimal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560f42649de9fa436b73517378a147ec21f6c997a546581df4b4b31677828934" +checksum = "4d6867f1565b3aad85681f1015055b087fcfd840d6aeee6eee7f2da317603695" dependencies = [ "autocfg", "libm", @@ -585,7 +609,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -614,7 +638,7 @@ dependencies = [ "mockall", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-tracker-clock", @@ -639,7 +663,7 @@ dependencies = [ "percent-encoding", "serde", "serde_bencode", - "thiserror 2.0.17", + "thiserror 2.0.18", "torrust-tracker-clock", "torrust-tracker-configuration", "torrust-tracker-contrib-bencode", @@ -675,7 +699,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "serde_repr", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "torrust-tracker-configuration", "torrust-tracker-located-error", @@ -701,7 +725,7 @@ dependencies = [ "serde", "serde_json", "testcontainers", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-rest-tracker-api-client", @@ -734,7 +758,7 @@ dependencies = [ "mockall", "rand 0.9.2", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-tracker-clock", @@ -847,7 +871,7 @@ dependencies = [ "serde_json", "serde_repr", "serde_urlencoded", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -907,7 +931,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1018,9 +1042,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.50" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ "find-msvc-tools", "jobserver", @@ -1028,6 +1052,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1051,9 +1081,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "num-traits", @@ -1111,9 +1141,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -1121,9 +1151,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -1140,14 +1170,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "clap_lex" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "cmake" @@ -1164,6 +1194,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "compact_str" version = "0.7.1" @@ -1179,9 +1219,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.35" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" +checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" dependencies = [ "brotli", "compression-core", @@ -1446,7 +1486,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1460,7 +1500,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1471,7 +1511,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1482,7 +1522,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1527,7 +1567,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1537,7 +1577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1559,7 +1599,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn 2.0.114", "unicode-xid", ] @@ -1571,7 +1611,7 @@ checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1598,7 +1638,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1618,6 +1658,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -1722,9 +1768,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ferroid" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce161062fb044bd629c2393590efd47cab8d0241faf15704ffb0d47b7b4e4a35" +checksum = "bb330bbd4cb7a5b9f559427f06f98a4f853a137c8298f3bd3f8ca57663e21986" dependencies = [ "portable-atomic", "rand 0.9.2", @@ -1749,27 +1795,26 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" dependencies = [ "crc32fast", "libz-sys", @@ -1788,6 +1833,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -1867,7 +1918,7 @@ checksum = "a0b4095fc99e1d858e5b8c7125d2638372ec85aa0fe6c807105cf10b0265ca6c" dependencies = [ "frunk_proc_macro_helpers", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1879,7 +1930,7 @@ dependencies = [ "frunk_core", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1891,19 +1942,25 @@ dependencies = [ "frunk_core", "frunk_proc_macro_helpers", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "fs-err" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824f08d01d0f496b3eca4f001a13cf17690a6ee930043d20817f547455fd98f8" +checksum = "baf68cef89750956493a66a10f512b9e58d9db21f2a573c079c0bdf1207a54a7" dependencies = [ "autocfg", "tokio", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -1979,7 +2036,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2030,13 +2087,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -2046,9 +2105,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -2060,7 +2121,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2089,9 +2150,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2099,7 +2160,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -2114,7 +2175,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy 0.8.31", + "zerocopy 0.8.34", ] [[package]] @@ -2140,7 +2201,7 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -2148,14 +2209,17 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hashlink" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2303,22 +2367,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.19" @@ -2337,7 +2385,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.6.2", "system-configuration", "tokio", "tower-service", @@ -2505,9 +2553,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -2547,9 +2595,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -2607,9 +2655,31 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.16" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" @@ -2623,9 +2693,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -2648,9 +2718,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libloading" @@ -2664,26 +2734,26 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", - "redox_syscall 0.6.0", + "redox_syscall 0.7.0", ] [[package]] name = "libsqlite3-sys" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a" dependencies = [ "cc", "pkg-config", @@ -2715,13 +2785,12 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "local-ip-address" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a60bf300a990b2d1ebdde4228e873e8e4da40d834adbf5265f3da1457ede652" +checksum = "92488bc8a0f99ee9f23577bdd06526d49657df8bd70504c61f812337cdad01ab" dependencies = [ "libc", "neli", - "thiserror 2.0.17", "windows-sys 0.61.2", ] @@ -2752,6 +2821,12 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchit" version = "0.8.4" @@ -2791,7 +2866,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2850,7 +2925,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2900,7 +2975,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "termcolor", "thiserror 1.0.69", ] @@ -2962,7 +3037,7 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", "security-framework 2.11.1", @@ -2996,7 +3071,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3059,9 +3134,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-integer" @@ -3153,7 +3228,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3162,6 +3237,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-sys" version = "0.9.111" @@ -3241,7 +3322,7 @@ dependencies = [ "regex", "regex-syntax", "structmeta", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3264,7 +3345,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3338,7 +3419,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3414,9 +3495,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "portable-atomic-util" @@ -3448,7 +3529,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.31", + "zerocopy 0.8.34", ] [[package]] @@ -3515,14 +3596,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -3535,16 +3616,16 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "version_check", "yansi", ] [[package]] name = "prost" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", "prost-derive", @@ -3552,22 +3633,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "prost-types" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" dependencies = [ "prost", ] @@ -3603,11 +3684,67 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -3641,9 +3778,9 @@ dependencies = [ [[package]] name = "r2d2_sqlite" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63417e83dc891797eea3ad379f52a5986da4bca0d6ef28baf4d14034dd111b0c" +checksum = "a2ebd03c29250cdf191da93a35118b4567c2ef0eacab54f65e058d6f4c9965f6" dependencies = [ "r2d2", "rusqlite", @@ -3674,7 +3811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -3694,7 +3831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -3703,14 +3840,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] @@ -3746,9 +3883,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96166dafa0886eb81fe1c0a388bece180fbef2135f97c1e2cf8302e74b43b5" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ "bitflags", ] @@ -3770,7 +3907,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3819,9 +3956,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" dependencies = [ "base64 0.22.1", "bytes", @@ -3833,21 +3970,21 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", - "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -3865,7 +4002,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -3884,9 +4021,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" dependencies = [ "bitvec", "bytecheck", @@ -3902,15 +4039,25 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "rsqlite-vfs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" +dependencies = [ + "hashbrown 0.16.1", + "thiserror 2.0.18", +] + [[package]] name = "rstest" version = "0.25.0" @@ -3948,7 +4095,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.111", + "syn 2.0.114", "unicode-ident", ] @@ -3966,15 +4113,15 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.111", + "syn 2.0.114", "unicode-ident", ] [[package]] name = "rusqlite" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3" dependencies = [ "bitflags", "fallible-iterator", @@ -3982,13 +4129,14 @@ dependencies = [ "hashlink", "libsqlite3-sys", "smallvec", + "sqlite-wasm-rs", ] [[package]] name = "rust_decimal" -version = "1.39.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" +checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" dependencies = [ "arrayvec", "borsh", @@ -4002,9 +4150,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -4036,10 +4184,11 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -4051,11 +4200,11 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", "security-framework 3.5.1", @@ -4072,19 +4221,48 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4098,9 +4276,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "same-file" @@ -4149,9 +4327,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" dependencies = [ "dyn-clone", "ref-cast", @@ -4260,7 +4438,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4270,7 +4448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "ryu", "serde_core", @@ -4278,16 +4456,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.146" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -4309,7 +4487,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4352,9 +4530,9 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.1.0", + "schemars 1.2.0", "serde_core", "serde_json", "serde_with_macros", @@ -4370,7 +4548,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4412,10 +4590,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -4461,14 +4640,26 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", ] +[[package]] +name = "sqlite-wasm-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4496,7 +4687,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4507,14 +4698,14 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "subprocess" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" +checksum = "f75238edb5be30a9ea3035b945eb9c319dde80e879411cdc9a8978e1ac822960" dependencies = [ "libc", "winapi", @@ -4560,9 +4751,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -4586,7 +4777,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4635,9 +4826,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", @@ -4673,9 +4864,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1483605f58b2fff80d786eb56a0b6b4e8b1e5423fbc9ec2e3e562fa2040d6f27" +checksum = "a81ec0158db5fbb9831e09d1813fe5ea9023a2b5e6e8e0a5fe67e2a820733629" dependencies = [ "astral-tokio-tar", "async-trait", @@ -4694,7 +4885,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -4722,11 +4913,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -4737,18 +4928,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4762,30 +4953,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" dependencies = [ "num-conv", "time-core", @@ -4828,16 +5019,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.2", "tokio-macros", "windows-sys 0.61.2", ] @@ -4850,17 +5041,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", + "syn 2.0.114", ] [[package]] @@ -4875,9 +5056,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -4886,9 +5067,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -4911,11 +5092,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.10+spec-1.1.0" +version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde_core", "serde_spanned 1.0.4", "toml_datetime 0.7.5+spec-1.1.0", @@ -4948,7 +5129,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -4962,7 +5143,7 @@ version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", @@ -5008,7 +5189,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2 0.6.1", + "socket2 0.6.2", "sync_wrapper", "tokio", "tokio-stream", @@ -5118,7 +5299,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "torrust-axum-server", "torrust-rest-tracker-api-client", @@ -5149,7 +5330,7 @@ dependencies = [ "hyper", "hyper-util", "pin-project-lite", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "torrust-server-lib", "torrust-tracker-configuration", @@ -5165,7 +5346,7 @@ dependencies = [ "hyper", "reqwest", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "url", "uuid", ] @@ -5220,7 +5401,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-axum-health-check-api-server", @@ -5256,7 +5437,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "torrust-tracker-configuration", "tracing", @@ -5284,8 +5465,8 @@ dependencies = [ "serde", "serde_json", "serde_with", - "thiserror 2.0.17", - "toml 0.9.10+spec-1.1.0", + "thiserror 2.0.18", + "toml 0.9.11+spec-1.1.0", "torrust-tracker-located-error", "tracing", "tracing-subscriber", @@ -5298,7 +5479,7 @@ name = "torrust-tracker-contrib-bencode" version = "3.0.0-develop" dependencies = [ "criterion 0.8.1", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5314,7 +5495,7 @@ dependencies = [ name = "torrust-tracker-located-error" version = "3.0.0-develop" dependencies = [ - "thiserror 2.0.17", + "thiserror 2.0.18", "tracing", ] @@ -5330,7 +5511,7 @@ dependencies = [ "rstest 0.25.0", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "torrust-tracker-primitives", "tracing", ] @@ -5347,7 +5528,7 @@ dependencies = [ "serde", "tdyne-peer-id", "tdyne-peer-id-registry", - "thiserror 2.0.17", + "thiserror 2.0.18", "torrust-tracker-configuration", "url", "zerocopy 0.7.35", @@ -5368,7 +5549,7 @@ dependencies = [ "rand 0.9.2", "rstest 0.26.1", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-tracker-clock", @@ -5427,7 +5608,7 @@ dependencies = [ "rand 0.9.2", "ringbuf", "serde", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "torrust-server-lib", @@ -5446,13 +5627,13 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.1", + "indexmap 2.13.0", "pin-project-lite", "slab", "sync_wrapper", @@ -5519,7 +5700,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5674,14 +5855,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -5704,9 +5886,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ "getrandom 0.3.4", "js-sys", @@ -5765,18 +5947,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -5787,11 +5969,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -5800,9 +5983,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5810,31 +5993,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -5850,11 +6033,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -5911,7 +6103,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5922,7 +6114,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5960,6 +6152,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5987,6 +6188,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -6020,6 +6236,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -6032,6 +6254,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -6044,6 +6272,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -6068,6 +6302,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -6080,6 +6320,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -6092,6 +6338,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -6104,6 +6356,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -6127,9 +6385,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" @@ -6181,7 +6439,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] @@ -6197,11 +6455,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "71ddd76bcebeed25db614f82bf31a9f4222d3fbba300e6fb6c00afa26cbd4d9d" dependencies = [ - "zerocopy-derive 0.8.31", + "zerocopy-derive 0.8.34", ] [[package]] @@ -6212,18 +6470,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "d8187381b52e32220d50b255276aa16a084ec0a9017a0ca2152a1f55c539758d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6243,7 +6501,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] @@ -6283,9 +6541,15 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] +[[package]] +name = "zmij" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" + [[package]] name = "zstd" version = "0.13.3" From 457a020c704d3ec084c0df222c15ca00e1c83f82 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 26 Jan 2026 13:06:09 +0000 Subject: [PATCH 26/79] fix: enable reqwest query feature for API compatibility reqwest 0.13 made the feature optional and disabled by default. This commit adds the feature to the reqwest dependency in the rest-tracker-api-client package to restore query parameter functionality. --- Cargo.lock | 1 + packages/rest-tracker-api-client/Cargo.toml | 2 +- .../rest-tracker-api-client/src/v1/client.rs | 20 +++++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 146da3a18..8916a6640 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3982,6 +3982,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", diff --git a/packages/rest-tracker-api-client/Cargo.toml b/packages/rest-tracker-api-client/Cargo.toml index cba580e18..c01b9c05a 100644 --- a/packages/rest-tracker-api-client/Cargo.toml +++ b/packages/rest-tracker-api-client/Cargo.toml @@ -16,7 +16,7 @@ version.workspace = true [dependencies] hyper = "1" -reqwest = { version = "0", features = ["json"] } +reqwest = { version = "0", features = ["json", "query"] } serde = { version = "1", features = ["derive"] } thiserror = "2" url = { version = "2", features = ["serde"] } diff --git a/packages/rest-tracker-api-client/src/v1/client.rs b/packages/rest-tracker-api-client/src/v1/client.rs index 3137b8b41..02a5b0d9c 100644 --- a/packages/rest-tracker-api-client/src/v1/client.rs +++ b/packages/rest-tracker-api-client/src/v1/client.rs @@ -204,22 +204,22 @@ impl Client { /// /// Will panic if the request can't be sent pub async fn get(path: Url, query: Option, headers: Option) -> Response { - let builder = reqwest::Client::builder() + let client = reqwest::Client::builder() .timeout(Duration::from_secs(DEFAULT_REQUEST_TIMEOUT_IN_SECS)) .build() .unwrap(); - let builder = match query { - Some(params) => builder.get(path).query(&ReqwestQuery::from(params)), - None => builder.get(path), - }; + let mut request_builder = client.get(path); - let builder = match headers { - Some(headers) => builder.headers(headers), - None => builder, - }; + if let Some(params) = query { + request_builder = request_builder.query(&ReqwestQuery::from(params)); + } + + if let Some(headers) = headers { + request_builder = request_builder.headers(headers); + } - builder.send().await.unwrap() + request_builder.send().await.unwrap() } /// Returns a `HeaderMap` with a request id header. From ac47c1b26a068cf371c35fe40660ccfb564f1de2 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 26 Jan 2026 14:08:13 +0000 Subject: [PATCH 27/79] fix: suppress clippy warnings for large error types in config tests --- packages/configuration/src/v2_0_0/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/configuration/src/v2_0_0/mod.rs b/packages/configuration/src/v2_0_0/mod.rs index 8391ba0e1..b3fbc881e 100644 --- a/packages/configuration/src/v2_0_0/mod.rs +++ b/packages/configuration/src/v2_0_0/mod.rs @@ -521,6 +521,7 @@ mod tests { } #[test] + #[allow(clippy::result_large_err)] fn configuration_should_use_the_default_values_when_only_the_mandatory_options_are_provided_by_the_user_via_toml_file() { figment::Jail::expect_with(|jail| { jail.create_file( @@ -552,6 +553,7 @@ mod tests { } #[test] + #[allow(clippy::result_large_err)] fn configuration_should_use_the_default_values_when_only_the_mandatory_options_are_provided_by_the_user_via_toml_content() { figment::Jail::expect_with(|_jail| { let config_toml = r#" @@ -581,6 +583,7 @@ mod tests { } #[test] + #[allow(clippy::result_large_err)] fn default_configuration_could_be_overwritten_from_a_single_env_var_with_toml_contents() { figment::Jail::expect_with(|_jail| { let config_toml = r#" @@ -613,6 +616,7 @@ mod tests { } #[test] + #[allow(clippy::result_large_err)] fn default_configuration_could_be_overwritten_from_a_toml_config_file() { figment::Jail::expect_with(|jail| { jail.create_file( @@ -646,6 +650,7 @@ mod tests { }); } + #[allow(clippy::result_large_err)] #[test] fn configuration_should_allow_to_overwrite_the_default_tracker_api_token_for_admin_with_an_env_var() { figment::Jail::expect_with(|jail| { From 046d5c982e34f7ace34e5e5355c8b72f540ad583 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 20 Feb 2026 11:08:46 +0000 Subject: [PATCH 28/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 98 packages to latest compatible versions Updating anyhow v1.0.100 -> v1.0.102 Updating arc-swap v1.8.0 -> v1.8.2 Updating async-compression v0.4.37 -> v0.4.40 Updating async-executor v1.13.3 -> v1.14.0 Updating aws-lc-rs v1.15.4 -> v1.16.0 Updating aws-lc-sys v0.37.0 -> v0.37.1 Updating bitflags v2.10.0 -> v2.11.0 Updating bollard v0.19.4 -> v0.20.1 Updating bollard-stubs v1.49.1-rc.28.4.0 -> v1.52.1-rc.29.1.3 Updating bumpalo v3.19.1 -> v3.20.2 Updating bytemuck v1.24.0 -> v1.25.0 Updating bytes v1.11.0 -> v1.11.1 Updating cc v1.2.54 -> v1.2.56 Adding chacha20 v0.10.0 Adding cipher v0.5.0 Updating clap v4.5.54 -> v4.5.60 Updating clap_builder v4.5.54 -> v4.5.60 Updating clap_derive v4.5.49 -> v4.5.55 Updating clap_lex v0.7.7 -> v1.0.0 Updating compression-codecs v0.4.36 -> v0.4.37 Adding cpufeatures v0.3.0 Updating criterion v0.8.1 -> v0.8.2 Updating criterion-plot v0.8.1 -> v0.8.2 Adding crypto-common v0.2.0 Updating deranged v0.5.5 -> v0.5.6 Adding env_filter v1.0.0 Updating env_logger v0.8.4 -> v0.11.9 Updating find-msvc-tools v0.1.8 -> v0.1.9 Updating flate2 v1.1.8 -> v1.1.9 Updating fs-err v3.2.2 -> v3.3.0 Updating futures v0.3.31 -> v0.3.32 Updating futures-channel v0.3.31 -> v0.3.32 Updating futures-core v0.3.31 -> v0.3.32 Updating futures-executor v0.3.31 -> v0.3.32 Updating futures-io v0.3.31 -> v0.3.32 Updating futures-macro v0.3.31 -> v0.3.32 Updating futures-sink v0.3.31 -> v0.3.32 Updating futures-task v0.3.31 -> v0.3.32 Updating futures-util v0.3.31 -> v0.3.32 Adding getrandom v0.4.1 Adding hybrid-array v0.4.7 Updating hyper-util v0.1.19 -> v0.1.20 Updating iana-time-zone v0.1.64 -> v0.1.65 Adding id-arena v2.3.0 Adding inout v0.2.2 Adding leb128fmt v0.1.0 Updating libc v0.2.180 -> v0.2.182 Updating local-ip-address v0.6.9 -> v0.6.10 Updating memchr v2.7.6 -> v2.8.0 Updating native-tls v0.2.14 -> v0.2.18 Updating neli v0.7.3 -> v0.7.4 Removing openssl-probe v0.1.6 Updating portable-atomic v1.13.0 -> v1.13.1 Updating portable-atomic-util v0.2.4 -> v0.2.5 Updating predicates v3.1.3 -> v3.1.4 Updating predicates-core v1.0.9 -> v1.0.10 Updating predicates-tree v1.0.12 -> v1.0.13 Adding prettyplease v0.2.37 Updating quickcheck v1.0.3 -> v1.1.0 Adding rand v0.10.0 Adding rand_core v0.10.0 Updating redox_syscall v0.7.0 -> v0.7.1 Updating regex v1.12.2 -> v1.12.3 Updating regex-automata v0.4.13 -> v0.4.14 Updating regex-syntax v0.8.8 -> v0.8.9 Updating reqwest v0.13.1 -> v0.13.2 Removing rustls-pemfile v2.2.0 Updating ryu v1.0.22 -> v1.0.23 Updating schemars v1.2.0 -> v1.2.1 Removing security-framework v2.11.1 Removing security-framework v3.5.1 Adding security-framework v3.7.0 Updating security-framework-sys v2.15.0 -> v2.17.0 Updating siphasher v1.0.1 -> v1.0.2 Updating slab v0.4.11 -> v0.4.12 Updating subprocess v0.2.13 -> v0.2.15 Updating syn v2.0.114 -> v2.0.117 Updating system-configuration v0.6.1 -> v0.7.0 Updating tempfile v3.24.0 -> v3.25.0 Updating testcontainers v0.26.3 -> v0.27.0 Updating time v0.3.46 -> v0.3.47 Updating time-macros v0.2.26 -> v0.2.27 Updating toml v0.9.11+spec-1.1.0 -> v0.9.12+spec-1.1.0 (available: v1.0.3+spec-1.1.0) Updating toml_parser v1.0.6+spec-1.1.0 -> v1.0.9+spec-1.1.0 Updating tonic v0.14.2 -> v0.14.5 Updating tonic-prost v0.14.2 -> v0.14.5 Updating unicode-ident v1.0.22 -> v1.0.24 Updating ureq v3.1.4 -> v3.2.0 Updating uuid v1.20.0 -> v1.21.0 Adding wasip3 v0.4.0+wasi-0.3.0-rc-2026-01-06 Adding wasm-encoder v0.244.0 Adding wasm-metadata v0.244.0 Adding wasmparser v0.244.0 Updating webpki-root-certs v1.0.5 -> v1.0.6 Removing webpki-roots v1.0.5 Adding wit-bindgen-core v0.51.0 Adding wit-bindgen-rust v0.51.0 Adding wit-bindgen-rust-macro v0.51.0 Adding wit-component v0.244.0 Adding wit-parser v0.244.0 Updating zerocopy v0.8.34 -> v0.8.39 Updating zerocopy-derive v0.8.34 -> v0.8.39 Updating zmij v1.0.17 -> v1.0.21 note: pass `--verbose` to see 7 unchanged dependencies behind latest ``` --- Cargo.lock | 767 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 485 insertions(+), 282 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8916a6640..e801b94cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "approx" @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" dependencies = [ "rustversion", ] @@ -239,9 +239,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.37" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d10e4f991a553474232bc0a31799f6d24b034a84c0971d80d2e2f78b2e576e40" +checksum = "7d67d43201f4d20c78bcda740c142ca52482d81da80681533d33bf3f0596c8e2" dependencies = [ "compression-codecs", "compression-core", @@ -251,9 +251,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -354,7 +354,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -371,7 +371,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -397,9 +397,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.15.4" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" dependencies = [ "aws-lc-sys", "zeroize", @@ -407,9 +407,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" +checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" dependencies = [ "cc", "cmake", @@ -514,7 +514,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -609,7 +609,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -620,9 +620,9 @@ checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bittorrent-http-tracker-core" @@ -721,7 +721,7 @@ dependencies = [ "r2d2", "r2d2_mysql", "r2d2_sqlite", - "rand 0.9.2", + "rand 0.10.0", "serde", "serde_json", "testcontainers", @@ -751,12 +751,12 @@ dependencies = [ "bittorrent-udp-tracker-protocol", "bloom", "blowfish", - "cipher", + "cipher 0.5.0", "criterion 0.5.1", "futures", "lazy_static", "mockall", - "rand 0.9.2", + "rand 0.10.0", "serde", "thiserror 2.0.18", "tokio", @@ -831,14 +831,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", - "cipher", + "cipher 0.4.4", ] [[package]] name = "bollard" -version = "0.19.4" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87a52479c9237eb04047ddb94788c41ca0d26eaff8b697ecfbb4c32f7fdc3b1b" +checksum = "227aa051deec8d16bd9c34605e7aaf153f240e35483dd42f6f78903847934738" dependencies = [ "async-stream", "base64 0.22.1", @@ -846,7 +846,6 @@ dependencies = [ "bollard-buildkit-proto", "bollard-stubs", "bytes", - "chrono", "futures-core", "futures-util", "hex", @@ -864,14 +863,13 @@ dependencies = [ "rand 0.9.2", "rustls", "rustls-native-certs", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_derive", "serde_json", - "serde_repr", "serde_urlencoded", "thiserror 2.0.18", + "time", "tokio", "tokio-stream", "tokio-util", @@ -896,19 +894,18 @@ dependencies = [ [[package]] name = "bollard-stubs" -version = "1.49.1-rc.28.4.0" +version = "1.52.1-rc.29.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623" +checksum = "0f0a8ca8799131c1837d1282c3f81f31e76ceb0ce426e04a7fe1ccee3287c066" dependencies = [ "base64 0.22.1", "bollard-buildkit-proto", "bytes", - "chrono", "prost", "serde", "serde_json", "serde_repr", - "serde_with", + "time", ] [[package]] @@ -931,7 +928,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -972,9 +969,9 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytecheck" @@ -1000,9 +997,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -1012,9 +1009,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "camino" @@ -1042,9 +1039,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.54" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -1079,6 +1076,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", +] + [[package]] name = "chrono" version = "0.4.43" @@ -1124,8 +1132,18 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", - "inout", + "crypto-common 0.1.7", + "inout 0.1.4", +] + +[[package]] +name = "cipher" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64727038c8c5e2bb503a15b9f5b9df50a1da9a33e83e1f93067d914f2c6604a5" +dependencies = [ + "crypto-common 0.2.0", + "inout 0.2.2", ] [[package]] @@ -1141,9 +1159,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -1151,9 +1169,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -1163,21 +1181,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "cmake" @@ -1219,9 +1237,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" +checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" dependencies = [ "brotli", "compression-core", @@ -1290,6 +1308,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -1329,16 +1356,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" dependencies = [ "alloca", "anes", "cast", "ciborium", "clap", - "criterion-plot 0.8.1", + "criterion-plot 0.8.2", "itertools 0.13.0", "num-traits", "oorandom", @@ -1365,9 +1392,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" dependencies = [ "cast", "itertools 0.13.0", @@ -1455,6 +1482,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" +dependencies = [ + "hybrid-array", +] + [[package]] name = "darling" version = "0.20.11" @@ -1486,7 +1522,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1500,7 +1536,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1511,7 +1547,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1522,7 +1558,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1541,9 +1577,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ "powerfmt", "serde_core", @@ -1567,7 +1603,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1577,7 +1613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1599,7 +1635,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.114", + "syn 2.0.117", "unicode-xid", ] @@ -1611,7 +1647,7 @@ checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1627,7 +1663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "crypto-common", + "crypto-common 0.1.7", ] [[package]] @@ -1638,7 +1674,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1686,15 +1722,25 @@ dependencies = [ ] [[package]] -name = "env_logger" -version = "0.8.4" +name = "env_filter" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", "regex", ] +[[package]] +name = "env_logger" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1806,15 +1852,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "libz-sys", @@ -1918,7 +1964,7 @@ checksum = "a0b4095fc99e1d858e5b8c7125d2638372ec85aa0fe6c807105cf10b0265ca6c" dependencies = [ "frunk_proc_macro_helpers", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1930,7 +1976,7 @@ dependencies = [ "frunk_core", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1942,14 +1988,14 @@ dependencies = [ "frunk_core", "frunk_proc_macro_helpers", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "fs-err" -version = "3.2.2" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf68cef89750956493a66a10f512b9e58d9db21f2a573c079c0bdf1207a54a7" +checksum = "73fde052dbfc920003cfd2c8e2c6e6d4cc7c1091538c3a24226cec0665ab08c0" dependencies = [ "autocfg", "tokio", @@ -1969,9 +2015,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1984,9 +2030,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1994,15 +2040,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -2011,9 +2057,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -2030,26 +2076,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" @@ -2059,9 +2105,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -2071,7 +2117,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2112,6 +2157,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "getset" version = "0.1.6" @@ -2121,7 +2180,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2175,7 +2234,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy 0.8.34", + "zerocopy 0.8.39", ] [[package]] @@ -2300,6 +2359,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.8.1" @@ -2369,14 +2437,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -2410,9 +2477,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2513,6 +2580,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -2578,6 +2651,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "hybrid-array", +] + [[package]] name = "io-enum" version = "1.2.0" @@ -2716,11 +2798,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.180" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libloading" @@ -2746,7 +2834,7 @@ checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags", "libc", - "redox_syscall 0.7.0", + "redox_syscall 0.7.1", ] [[package]] @@ -2785,9 +2873,9 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "local-ip-address" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92488bc8a0f99ee9f23577bdd06526d49657df8bd70504c61f812337cdad01ab" +checksum = "79ef8c257c92ade496781a32a581d43e3d512cf8ce714ecf04ea80f93ed0ff4a" dependencies = [ "libc", "neli", @@ -2835,9 +2923,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "miette" @@ -2866,7 +2954,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2925,7 +3013,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2975,7 +3063,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "termcolor", "thiserror 1.0.69", ] @@ -3030,26 +3118,26 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe 0.1.6", + "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "neli" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23bebbf3e157c402c4d5ee113233e5e0610cc27453b2f07eefce649c7365dcc" +checksum = "22f9786d56d972959e1408b6a93be6af13b9c1392036c5c1fafa08a1b0c6ee87" dependencies = [ "bitflags", "byteorder", @@ -3071,7 +3159,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3228,15 +3316,9 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -3322,7 +3404,7 @@ dependencies = [ "regex", "regex-syntax", "structmeta", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3345,7 +3427,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3419,7 +3501,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3495,15 +3577,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ "portable-atomic", ] @@ -3529,14 +3611,14 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.34", + "zerocopy 0.8.39", ] [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "predicates-core", @@ -3544,15 +3626,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", @@ -3568,6 +3650,16 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -3596,7 +3688,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3616,7 +3708,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "version_check", "yansi", ] @@ -3641,7 +3733,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3675,13 +3767,13 @@ dependencies = [ [[package]] name = "quickcheck" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b" dependencies = [ "env_logger", "log", - "rand 0.8.5", + "rand 0.10.0", ] [[package]] @@ -3814,6 +3906,17 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom 0.4.1", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -3852,6 +3955,12 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "rayon" version = "1.11.0" @@ -3883,9 +3992,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" dependencies = [ "bitflags", ] @@ -3907,14 +4016,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -3924,9 +4033,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -3935,9 +4044,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "relative-path" @@ -3956,9 +4065,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" dependencies = [ "base64 0.22.1", "bytes", @@ -4096,7 +4205,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.114", + "syn 2.0.117", "unicode-ident", ] @@ -4114,7 +4223,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.114", + "syn 2.0.117", "unicode-ident", ] @@ -4205,19 +4314,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", + "security-framework", ] [[package]] @@ -4245,7 +4345,7 @@ dependencies = [ "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki", - "security-framework 3.5.1", + "security-framework", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -4277,9 +4377,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -4328,9 +4428,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -4352,22 +4452,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags", "core-foundation 0.10.1", @@ -4378,9 +4465,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -4439,7 +4526,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4488,7 +4575,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4533,7 +4620,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -4549,7 +4636,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4559,7 +4646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -4570,7 +4657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -4613,15 +4700,15 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -4688,7 +4775,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta-derive", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4699,14 +4786,14 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "subprocess" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75238edb5be30a9ea3035b945eb9c319dde80e879411cdc9a8978e1ac822960" +checksum = "2c56e8662b206b9892d7a5a3f2ecdbcb455d3d6b259111373b7e08b8055158a8" dependencies = [ "libc", "winapi", @@ -4752,9 +4839,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4778,14 +4865,14 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ "bitflags", "core-foundation 0.9.4", @@ -4827,12 +4914,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.24.0" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.1", "once_cell", "rustix", "windows-sys 0.61.2", @@ -4865,9 +4952,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.26.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a81ec0158db5fbb9831e09d1813fe5ea9023a2b5e6e8e0a5fe67e2a820733629" +checksum = "c3fdcea723c64cc08dbc533b3761e345a15bf1222cbe6cb611de09b43f17a168" dependencies = [ "astral-tokio-tar", "async-trait", @@ -4878,6 +4965,7 @@ dependencies = [ "etcetera", "ferroid", "futures", + "http", "itertools 0.14.0", "log", "memchr", @@ -4929,7 +5017,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4940,7 +5028,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4954,9 +5042,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -4975,9 +5063,9 @@ checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -5042,7 +5130,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -5093,9 +5181,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.11+spec-1.1.0" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap 2.13.0", "serde_core", @@ -5152,9 +5240,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ "winnow", ] @@ -5173,9 +5261,9 @@ checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tonic" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" dependencies = [ "async-trait", "axum", @@ -5202,9 +5290,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" dependencies = [ "bytes", "prost", @@ -5256,7 +5344,7 @@ dependencies = [ "hyper", "local-ip-address", "percent-encoding", - "rand 0.9.2", + "rand 0.10.0", "reqwest", "serde", "serde_bencode", @@ -5397,7 +5485,7 @@ dependencies = [ "clap", "local-ip-address", "mockall", - "rand 0.9.2", + "rand 0.10.0", "regex", "reqwest", "serde", @@ -5467,7 +5555,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror 2.0.18", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", "torrust-tracker-located-error", "tracing", "tracing-subscriber", @@ -5479,7 +5567,7 @@ dependencies = [ name = "torrust-tracker-contrib-bencode" version = "3.0.0-develop" dependencies = [ - "criterion 0.8.1", + "criterion 0.8.2", "thiserror 2.0.18", ] @@ -5543,11 +5631,11 @@ dependencies = [ "async-std", "bittorrent-primitives", "chrono", - "criterion 0.8.1", + "criterion 0.8.2", "crossbeam-skiplist", "futures", "mockall", - "rand 0.9.2", + "rand 0.10.0", "rstest 0.26.1", "serde", "thiserror 2.0.18", @@ -5566,7 +5654,7 @@ dependencies = [ name = "torrust-tracker-test-helpers" version = "3.0.0-develop" dependencies = [ - "rand 0.9.2", + "rand 0.10.0", "torrust-tracker-configuration", "tracing", "tracing-subscriber", @@ -5579,7 +5667,7 @@ dependencies = [ "aquatic_udp_protocol", "async-std", "bittorrent-primitives", - "criterion 0.8.1", + "criterion 0.8.2", "crossbeam-skiplist", "dashmap", "futures", @@ -5606,7 +5694,7 @@ dependencies = [ "futures-util", "local-ip-address", "mockall", - "rand 0.9.2", + "rand 0.10.0", "ringbuf", "serde", "thiserror 2.0.18", @@ -5701,7 +5789,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -5786,9 +5874,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-linebreak" @@ -5828,9 +5916,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.1.4" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" dependencies = [ "base64 0.22.1", "log", @@ -5839,7 +5927,6 @@ dependencies = [ "rustls-pki-types", "ureq-proto", "utf-8", - "webpki-roots", ] [[package]] @@ -5887,11 +5974,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", "rand 0.9.2", "wasm-bindgen", @@ -5955,6 +6042,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.108" @@ -6001,7 +6097,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -6014,6 +6110,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "web-sys" version = "0.3.85" @@ -6036,18 +6166,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -6104,7 +6225,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6115,7 +6236,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6389,6 +6510,88 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" @@ -6440,7 +6643,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -6456,11 +6659,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.34" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ddd76bcebeed25db614f82bf31a9f4222d3fbba300e6fb6c00afa26cbd4d9d" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ - "zerocopy-derive 0.8.34", + "zerocopy-derive 0.8.39", ] [[package]] @@ -6471,18 +6674,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "zerocopy-derive" -version = "0.8.34" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8187381b52e32220d50b255276aa16a084ec0a9017a0ca2152a1f55c539758d" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6502,7 +6705,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -6542,14 +6745,14 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "zmij" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zstd" From f737ace07747c99ef6d393d7cacdff4d7083532b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Fri, 20 Feb 2026 11:58:56 +0000 Subject: [PATCH 29/79] fix: resolve compilation errors after dependency updates BREAKING CHANGE: cipher crate pinned to v0.4 for compatibility with blowfish - Replace Rng import with RngExt for sample_iter method in rand 0.10 - Pin cipher crate to v0.4 to match blowfish dependency constraints - Add explicit generic-array dependency to udp-tracker-core - Import GenericArray directly from generic_array crate - Update Keeper trait in crypto/keys.rs to use BlockEncrypt + BlockDecrypt bounds - Add BlockEncrypt and BlockDecrypt trait imports to connection_cookie.rs - Fix imports in: - packages/tracker-core/src/authentication/key/peer_key.rs - packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs - packages/udp-tracker-core/src/crypto/keys.rs - packages/test-helpers/src/random.rs - src/console/ci/e2e/tracker_container.rs --- Cargo.lock | 48 +++---------------- packages/test-helpers/src/random.rs | 2 +- .../src/authentication/key/peer_key.rs | 2 +- packages/tracker-core/src/test_helpers.rs | 2 +- packages/udp-tracker-core/Cargo.toml | 3 +- .../src/crypto/ephemeral_instance_keys.rs | 4 +- packages/udp-tracker-core/src/crypto/keys.rs | 4 +- src/console/ci/e2e/tracker_container.rs | 2 +- 8 files changed, 17 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e801b94cb..c6b151951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -751,9 +751,10 @@ dependencies = [ "bittorrent-udp-tracker-protocol", "bloom", "blowfish", - "cipher 0.5.0", + "cipher", "criterion 0.5.1", "futures", + "generic-array", "lazy_static", "mockall", "rand 0.10.0", @@ -831,7 +832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", - "cipher 0.4.4", + "cipher", ] [[package]] @@ -1132,18 +1133,8 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", - "inout 0.1.4", -] - -[[package]] -name = "cipher" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64727038c8c5e2bb503a15b9f5b9df50a1da9a33e83e1f93067d914f2c6604a5" -dependencies = [ - "crypto-common 0.2.0", - "inout 0.2.2", + "crypto-common", + "inout", ] [[package]] @@ -1482,15 +1473,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" -dependencies = [ - "hybrid-array", -] - [[package]] name = "darling" version = "0.20.11" @@ -1663,7 +1645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "crypto-common 0.1.7", + "crypto-common", ] [[package]] @@ -2359,15 +2341,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hybrid-array" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" -dependencies = [ - "typenum", -] - [[package]] name = "hyper" version = "1.8.1" @@ -2651,15 +2624,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "inout" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" -dependencies = [ - "hybrid-array", -] - [[package]] name = "io-enum" version = "1.2.0" diff --git a/packages/test-helpers/src/random.rs b/packages/test-helpers/src/random.rs index f096d695c..62265dbd7 100644 --- a/packages/test-helpers/src/random.rs +++ b/packages/test-helpers/src/random.rs @@ -1,6 +1,6 @@ //! Random data generators for testing. use rand::distr::Alphanumeric; -use rand::{rng, Rng}; +use rand::{rng, RngExt}; /// Returns a random alphanumeric string of a certain size. /// diff --git a/packages/tracker-core/src/authentication/key/peer_key.rs b/packages/tracker-core/src/authentication/key/peer_key.rs index 41aba950b..ba648ad2f 100644 --- a/packages/tracker-core/src/authentication/key/peer_key.rs +++ b/packages/tracker-core/src/authentication/key/peer_key.rs @@ -13,7 +13,7 @@ use std::time::Duration; use derive_more::Display; use rand::distr::Alphanumeric; -use rand::{rng, Rng}; +use rand::{rng, RngExt}; use serde::{Deserialize, Serialize}; use thiserror::Error; use torrust_tracker_clock::conv::convert_from_timestamp_to_datetime_utc; diff --git a/packages/tracker-core/src/test_helpers.rs b/packages/tracker-core/src/test_helpers.rs index 62649cd22..bf21e6f94 100644 --- a/packages/tracker-core/src/test_helpers.rs +++ b/packages/tracker-core/src/test_helpers.rs @@ -7,7 +7,7 @@ pub(crate) mod tests { use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId}; use bittorrent_primitives::info_hash::InfoHash; - use rand::Rng; + use rand::RngExt; use torrust_tracker_configuration::Configuration; #[cfg(test)] use torrust_tracker_configuration::Core; diff --git a/packages/udp-tracker-core/Cargo.toml b/packages/udp-tracker-core/Cargo.toml index b3007eb80..aa12f898f 100644 --- a/packages/udp-tracker-core/Cargo.toml +++ b/packages/udp-tracker-core/Cargo.toml @@ -20,9 +20,10 @@ bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" bittorrent-udp-tracker-protocol = { version = "3.0.0-develop", path = "../udp-protocol" } bloom = "0.3.2" blowfish = "0" -cipher = "0" +cipher = "0.4" criterion = { version = "0.5.1", features = ["async_tokio"] } futures = "0" +generic-array = "0" lazy_static = "1" rand = "0" serde = "1.0.219" diff --git a/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs b/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs index 58ba70562..de40e4b1d 100644 --- a/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs +++ b/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs @@ -4,10 +4,10 @@ //! application starts and are not persisted anywhere. use blowfish::BlowfishLE; -use cipher::generic_array::GenericArray; use cipher::{BlockSizeUser, KeyInit}; +use generic_array::GenericArray; use rand::rngs::ThreadRng; -use rand::Rng; +use rand::RngExt; pub type Seed = [u8; 32]; pub type CipherBlowfish = BlowfishLE; diff --git a/packages/udp-tracker-core/src/crypto/keys.rs b/packages/udp-tracker-core/src/crypto/keys.rs index f9a3e361d..bb813b9dc 100644 --- a/packages/udp-tracker-core/src/crypto/keys.rs +++ b/packages/udp-tracker-core/src/crypto/keys.rs @@ -5,6 +5,8 @@ //! //! It also provides the logic for the cipher for encryption and decryption. +use cipher::{BlockDecrypt, BlockEncrypt}; + use self::detail_cipher::CURRENT_CIPHER; use self::detail_seed::CURRENT_SEED; pub use crate::crypto::ephemeral_instance_keys::CipherArrayBlowfish; @@ -13,7 +15,7 @@ use crate::crypto::ephemeral_instance_keys::{CipherBlowfish, Seed, RANDOM_CIPHER /// This trait is for structures that can keep and provide a seed. pub trait Keeper { type Seed: Sized + Default + AsMut<[u8]>; - type Cipher: cipher::BlockCipher; + type Cipher: BlockEncrypt + BlockDecrypt; /// It returns a reference to the seed that is keeping. fn get_seed() -> &'static Self::Seed; diff --git a/src/console/ci/e2e/tracker_container.rs b/src/console/ci/e2e/tracker_container.rs index a3845c103..1a7717a41 100644 --- a/src/console/ci/e2e/tracker_container.rs +++ b/src/console/ci/e2e/tracker_container.rs @@ -1,7 +1,7 @@ use std::time::Duration; use rand::distr::Alphanumeric; -use rand::Rng; +use rand::RngExt; use super::docker::{RunOptions, RunningContainer}; use super::logs_parser::RunningServices; From ed0937bfe450a306de84f90660683c7a7fb16f56 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 3 Mar 2026 07:55:53 +0000 Subject: [PATCH 30/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 35 packages to latest compatible versions Updating async-compression v0.4.40 -> v0.4.41 Updating aws-lc-rs v1.16.0 -> v1.16.1 Updating aws-lc-sys v0.37.1 -> v0.38.0 Updating chrono v0.4.43 -> v0.4.44 Updating deranged v0.5.6 -> v0.5.8 Updating derive_utils v0.15.0 -> v0.15.1 Updating io-enum v1.2.0 -> v1.2.1 Updating ipnet v2.11.0 -> v2.12.0 Updating js-sys v0.3.85 -> v0.3.91 Updating libredox v0.1.12 -> v0.1.14 Updating libz-sys v1.1.23 -> v1.1.24 Updating linux-raw-sys v0.11.0 -> v0.12.1 Updating owo-colors v4.2.3 -> v4.3.0 Updating pin-project v1.1.10 -> v1.1.11 Updating pin-project-internal v1.1.10 -> v1.1.11 Updating pin-project-lite v0.2.16 -> v0.2.17 Updating piper v0.2.4 -> v0.2.5 Adding plain v0.2.3 Updating redox_syscall v0.7.1 -> v0.7.3 Updating regex-syntax v0.8.9 -> v0.8.10 Updating rustix v1.1.3 -> v1.1.4 Updating rustls v0.23.36 -> v0.23.37 Updating serde_with v3.16.1 -> v3.17.0 Updating serde_with_macros v3.16.1 -> v3.17.0 Updating tempfile v3.25.0 -> v3.26.0 Updating testcontainers v0.27.0 -> v0.27.1 Updating tokio-macros v2.6.0 -> v2.6.1 Updating wasm-bindgen v0.2.108 -> v0.2.114 Updating wasm-bindgen-futures v0.4.58 -> v0.4.64 Updating wasm-bindgen-macro v0.2.108 -> v0.2.114 Updating wasm-bindgen-macro-support v0.2.108 -> v0.2.114 Updating wasm-bindgen-shared v0.2.108 -> v0.2.114 Updating web-sys v0.3.85 -> v0.3.91 Updating zerocopy v0.8.39 -> v0.8.40 Updating zerocopy-derive v0.8.39 -> v0.8.40 note: pass `--verbose` to see 9 unchanged dependencies behind latest ``` --- Cargo.lock | 151 ++++++++++++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c6b151951..6894e2bcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -239,9 +239,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d67d43201f4d20c78bcda740c142ca52482d81da80681533d33bf3f0596c8e2" +checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" dependencies = [ "compression-codecs", "compression-core", @@ -397,9 +397,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" +checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf" dependencies = [ "aws-lc-sys", "zeroize", @@ -407,9 +407,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e" dependencies = [ "cc", "cmake", @@ -1090,9 +1090,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "num-traits", @@ -1559,9 +1559,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -1623,9 +1623,9 @@ dependencies = [ [[package]] name = "derive_utils" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" +checksum = "362f47930db19fe7735f527e6595e4900316b893ebf6d48ad3d31be928d57dd6" dependencies = [ "proc-macro2", "quote", @@ -2216,7 +2216,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy 0.8.39", + "zerocopy 0.8.40", ] [[package]] @@ -2626,18 +2626,18 @@ dependencies = [ [[package]] name = "io-enum" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d197db2f7ebf90507296df3aebaf65d69f5dce8559d8dbd82776a6cadab61bbf" +checksum = "7de9008599afe8527a8c9d70423437363b321649161e98473f433de802d76107" dependencies = [ "derive_utils", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" @@ -2739,9 +2739,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -2792,13 +2792,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags", "libc", - "redox_syscall 0.7.1", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -2814,9 +2815,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "4735e9cbde5aac84a5ce588f6b23a90b9b0b528f6c5a8db8a4aff300463a0839" dependencies = [ "cc", "pkg-config", @@ -2825,9 +2826,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -3303,9 +3304,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "page_size" @@ -3450,18 +3451,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", @@ -3470,9 +3471,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -3482,9 +3483,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -3497,6 +3498,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "plotters" version = "0.3.7" @@ -3575,7 +3582,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.39", + "zerocopy 0.8.40", ] [[package]] @@ -3956,9 +3963,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags", ] @@ -4008,9 +4015,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "relative-path" @@ -4245,9 +4252,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -4258,9 +4265,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "aws-lc-rs", "log", @@ -4574,9 +4581,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" dependencies = [ "base64 0.22.1", "chrono", @@ -4593,9 +4600,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -4878,9 +4885,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.25.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", "getrandom 0.4.1", @@ -4916,9 +4923,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fdcea723c64cc08dbc533b3761e345a15bf1222cbe6cb611de09b43f17a168" +checksum = "c1c0624faaa317c56d6d19136580be889677259caf5c897941c6f446b4655068" dependencies = [ "astral-tokio-tar", "async-trait", @@ -5088,9 +5095,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", @@ -6017,9 +6024,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -6030,9 +6037,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -6044,9 +6051,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6054,9 +6061,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", @@ -6067,9 +6074,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -6110,9 +6117,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -6623,11 +6630,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ - "zerocopy-derive 0.8.39", + "zerocopy-derive 0.8.40", ] [[package]] @@ -6643,9 +6650,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", From 29edbb6d154f2230d7695d2bd47ca5084fbc53a4 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 3 Mar 2026 08:04:34 +0000 Subject: [PATCH 31/79] fix: collapse nested if into match arm guard in pagination test Resolves clippy::collapsible_match lint by moving the inner if condition into the match arm guard for the Pagination { limit: 1, offset: 1 } case. --- .../tests/repository/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/torrent-repository-benchmarking/tests/repository/mod.rs b/packages/torrent-repository-benchmarking/tests/repository/mod.rs index c3589ce68..ec7e68bae 100644 --- a/packages/torrent-repository-benchmarking/tests/repository/mod.rs +++ b/packages/torrent-repository-benchmarking/tests/repository/mod.rs @@ -364,12 +364,10 @@ async fn it_should_get_paginated( } // it should return the only the second entry if both the limit and the offset are one. - Pagination { limit: 1, offset: 1 } => { - if info_hashes.len() > 1 { - let page = repo.get_paginated(Some(&paginated)).await; - assert_eq!(page.len(), 1); - assert_eq!(page[0].0, info_hashes[1]); - } + Pagination { limit: 1, offset: 1 } if info_hashes.len() > 1 => { + let page = repo.get_paginated(Some(&paginated)).await; + assert_eq!(page.len(), 1); + assert_eq!(page[0].0, info_hashes[1]); } // the other cases are not yet tested. _ => {} From 7e322eb7bf766f2a6c5ee376b42deae21b28bcd9 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 3 Mar 2026 08:08:11 +0000 Subject: [PATCH 32/79] ci: upgrade actions/upload-artifact from v6 to v7 in generate_coverage_pr workflow --- .github/workflows/generate_coverage_pr.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/generate_coverage_pr.yaml b/.github/workflows/generate_coverage_pr.yaml index f762207cf..a3f97dbf2 100644 --- a/.github/workflows/generate_coverage_pr.yaml +++ b/.github/workflows/generate_coverage_pr.yaml @@ -59,13 +59,13 @@ jobs: # Triggered sub-workflow is not able to detect the original commit/PR which is available # in this workflow. - name: Store PR number - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: pr_number path: pr_number.txt - name: Store commit SHA - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: commit_sha path: commit_sha.txt @@ -74,7 +74,7 @@ jobs: # is executed by a different workflow `upload_coverage.yml`. The reason for this # split is because `on.pull_request` workflows don't have access to secrets. - name: Store coverage report in artifacts - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: codecov_report path: ./codecov.json From de471450fb2a555816b111cd59ae03dade2b6fcb Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 3 Mar 2026 18:14:57 +0000 Subject: [PATCH 33/79] fix: add sleep after HTTP server stop in health check test to avoid race condition --- packages/axum-health-check-api-server/tests/server/contract.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/axum-health-check-api-server/tests/server/contract.rs b/packages/axum-health-check-api-server/tests/server/contract.rs index 1d1ba3539..af1c0cff9 100644 --- a/packages/axum-health-check-api-server/tests/server/contract.rs +++ b/packages/axum-health-check-api-server/tests/server/contract.rs @@ -202,6 +202,9 @@ mod http { service.server.stop().await.expect("it should stop udp server"); + // Give the OS a moment to fully release the TCP port after the server stops. + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + { let config = configuration.health_check_api.clone(); let env = Started::new(&config.into(), registar).await; From 1228a2b986e41fa195fd5418a5fecd028add1524 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Tue, 7 Apr 2026 19:07:53 +0100 Subject: [PATCH 34/79] chore(deps): update dependencies ``` Updating crates.io index Locking 104 packages to latest compatible versions Updating anstream v0.6.21 -> v1.0.0 Updating anstyle v1.0.13 -> v1.0.14 Updating anstyle-parse v0.2.7 -> v1.0.0 Updating arc-swap v1.8.2 -> v1.9.1 Updating astral-tokio-tar v0.5.6 -> v0.6.0 Updating aws-lc-rs v1.16.1 -> v1.16.2 Updating aws-lc-sys v0.38.0 -> v0.39.1 Updating bollard v0.20.1 -> v0.20.2 Updating borsh v1.6.0 -> v1.6.1 Updating borsh-derive v1.6.0 -> v1.6.1 Updating cc v1.2.56 -> v1.2.59 Updating clap v4.5.60 -> v4.6.0 Updating clap_builder v4.5.60 -> v4.6.0 Updating clap_derive v4.5.55 -> v4.6.0 Updating clap_lex v1.0.0 -> v1.1.0 Updating cmake v0.1.57 -> v0.1.58 Updating colorchoice v1.0.4 -> v1.0.5 Updating darling v0.21.3 -> v0.23.0 Updating darling_core v0.21.3 -> v0.23.0 Updating darling_macro v0.21.3 -> v0.23.0 Updating env_filter v1.0.0 -> v1.0.1 Updating env_logger v0.11.9 -> v0.11.10 Updating fastrand v2.3.0 -> v2.4.1 Updating fragile v2.0.1 -> v2.1.0 Updating getrandom v0.4.1 -> v0.4.2 Updating hyper v1.8.1 -> v1.9.0 Updating icu_collections v2.1.1 -> v2.2.0 Updating icu_locale_core v2.1.1 -> v2.2.0 Updating icu_normalizer v2.1.1 -> v2.2.0 Updating icu_normalizer_data v2.1.1 -> v2.2.0 Updating icu_properties v2.1.2 -> v2.2.0 Updating icu_properties_data v2.1.2 -> v2.2.0 Updating icu_provider v2.1.1 -> v2.2.0 Updating indexmap v2.13.0 -> v2.13.1 Updating iri-string v0.7.10 -> v0.7.12 Updating itoa v1.0.17 -> v1.0.18 Removing jni-sys v0.3.0 Adding jni-sys v0.3.1 Adding jni-sys v0.4.1 Adding jni-sys-macros v0.4.1 Updating js-sys v0.3.91 -> v0.3.94 Updating libc v0.2.182 -> v0.2.184 Updating libredox v0.1.14 -> v0.1.15 Updating libsqlite3-sys v0.36.0 -> v0.37.0 Updating libz-sys v1.1.24 -> v1.1.28 Updating litemap v0.8.1 -> v0.8.2 Updating local-ip-address v0.6.10 -> v0.6.11 Updating mio v1.1.1 -> v1.2.0 Updating num-conv v0.2.0 -> v0.2.1 Updating once_cell v1.21.3 -> v1.21.4 Updating openssl v0.10.75 -> v0.10.76 Updating openssl-sys v0.9.111 -> v0.9.112 Updating portable-atomic-util v0.2.5 -> v0.2.6 Updating potential_utf v0.1.4 -> v0.1.5 Updating proc-macro-crate v3.4.0 -> v3.5.0 Updating quinn-proto v0.11.13 -> v0.11.14 Updating quote v1.0.44 -> v1.0.45 Adding r-efi v6.0.0 Updating r2d2_sqlite v0.32.0 -> v0.33.0 Updating rusqlite v0.38.0 -> v0.39.0 Updating rust_decimal v1.40.0 -> v1.41.0 Updating rustc-hash v2.1.1 -> v2.1.2 Updating rustls-webpki v0.103.9 -> v0.103.10 Updating schannel v0.1.28 -> v0.1.29 Updating semver v1.0.27 -> v1.0.28 Updating serde_spanned v1.0.4 -> v1.1.1 Updating serde_with v3.17.0 -> v3.18.0 Updating serde_with_macros v3.17.0 -> v3.18.0 Updating simd-adler32 v0.3.8 -> v0.3.9 Updating socket2 v0.6.2 -> v0.6.3 Updating tempfile v3.26.0 -> v3.27.0 Updating terminal_size v0.4.3 -> v0.4.4 Updating testcontainers v0.27.1 -> v0.27.2 Updating tinystr v0.8.2 -> v0.8.3 Updating tinyvec v1.10.0 -> v1.11.0 Updating tokio v1.49.0 -> v1.51.0 Updating tokio-macros v2.6.1 -> v2.7.0 Adding toml_datetime v1.1.1+spec-1.1.0 Updating toml_edit v0.23.10+spec-1.0.0 -> v0.25.10+spec-1.1.0 Updating toml_parser v1.0.9+spec-1.1.0 -> v1.1.2+spec-1.1.0 Updating toml_writer v1.0.6+spec-1.1.0 -> v1.1.1+spec-1.1.0 Updating tracing-subscriber v0.3.22 -> v0.3.23 Updating unicode-segmentation v1.12.0 -> v1.13.2 Updating ureq v3.2.0 -> v3.3.0 Updating ureq-proto v0.5.3 -> v0.6.0 Removing utf-8 v0.7.6 Adding utf8-zero v0.8.1 Updating uuid v1.21.0 -> v1.23.0 Updating wasm-bindgen v0.2.114 -> v0.2.117 Updating wasm-bindgen-futures v0.4.64 -> v0.4.67 Updating wasm-bindgen-macro v0.2.114 -> v0.2.117 Updating wasm-bindgen-macro-support v0.2.114 -> v0.2.117 Updating wasm-bindgen-shared v0.2.114 -> v0.2.117 Updating web-sys v0.3.91 -> v0.3.94 Removing winnow v0.7.14 Adding winnow v0.7.15 Adding winnow v1.0.1 Updating writeable v0.6.2 -> v0.6.3 Updating yoke v0.8.1 -> v0.8.2 Updating yoke-derive v0.8.1 -> v0.8.2 Updating zerocopy v0.8.40 -> v0.8.48 Updating zerocopy-derive v0.8.40 -> v0.8.48 Updating zerofrom v0.1.6 -> v0.1.7 Updating zerofrom-derive v0.1.6 -> v0.1.7 Updating zerotrie v0.2.3 -> v0.2.4 Updating zerovec v0.11.5 -> v0.11.6 Updating zerovec-derive v0.11.2 -> v0.11.3 note: pass `--verbose` to see 9 unchanged dependencies behind latest ``` --- Cargo.lock | 543 +++++++++++++++++++++++++++++------------------------ 1 file changed, 296 insertions(+), 247 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6894e2bcd..9e0911944 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,9 +84,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -99,15 +99,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -175,9 +175,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" dependencies = [ "rustversion", ] @@ -190,9 +190,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "astral-tokio-tar" -version = "0.5.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec179a06c1769b1e42e1e2cbe74c7dcdb3d6383c838454d063eaac5bbb7ebbe5" +checksum = "3c23f3af104b40a3430ccb90ed5f7bd877a8dc5c26fc92fde51a22b40890dcf9" dependencies = [ "filetime", "futures-core", @@ -397,9 +397,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.1" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" dependencies = [ "aws-lc-sys", "zeroize", @@ -407,9 +407,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.38.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" dependencies = [ "cc", "cmake", @@ -837,9 +837,9 @@ dependencies = [ [[package]] name = "bollard" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227aa051deec8d16bd9c34605e7aaf153f240e35483dd42f6f78903847934738" +checksum = "ee04c4c84f1f811b017f2fbb7dd8815c976e7ca98593de9c1e2afad0f636bff4" dependencies = [ "async-stream", "base64 0.22.1", @@ -911,19 +911,20 @@ dependencies = [ [[package]] name = "borsh" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", @@ -1040,9 +1041,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -1150,9 +1151,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -1160,9 +1161,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -1172,9 +1173,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", @@ -1184,24 +1185,24 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmake" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -1485,12 +1486,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -1509,11 +1510,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -1534,11 +1534,11 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core 0.21.3", + "darling_core 0.23.0", "quote", "syn 2.0.117", ] @@ -1705,9 +1705,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -1715,9 +1715,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "env_filter", "log", @@ -1790,9 +1790,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "ferroid" @@ -1913,9 +1913,12 @@ dependencies = [ [[package]] name = "fragile" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9" +dependencies = [ + "futures-core", +] [[package]] name = "frunk" @@ -2134,20 +2137,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.0", "wasip2", "wasip3", @@ -2201,7 +2204,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.0", + "indexmap 2.13.1", "slab", "tokio", "tokio-util", @@ -2216,7 +2219,7 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "zerocopy 0.8.40", + "zerocopy 0.8.48", ] [[package]] @@ -2343,9 +2346,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -2358,7 +2361,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -2425,7 +2427,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.6.3", "system-configuration", "tokio", "tower-service", @@ -2474,12 +2476,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -2487,9 +2490,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -2500,9 +2503,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -2514,15 +2517,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -2534,15 +2537,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -2599,9 +2602,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -2641,9 +2644,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -2701,9 +2704,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" @@ -2714,7 +2717,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", @@ -2723,9 +2726,31 @@ dependencies = [ [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "jobserver" @@ -2739,10 +2764,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -2770,9 +2797,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libloading" @@ -2792,9 +2819,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ "bitflags", "libc", @@ -2804,9 +2831,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.36.0" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a" +checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" dependencies = [ "cc", "pkg-config", @@ -2815,9 +2842,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.24" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4735e9cbde5aac84a5ce588f6b23a90b9b0b528f6c5a8db8a4aff300463a0839" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "pkg-config", @@ -2832,15 +2859,15 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "local-ip-address" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ef8c257c92ade496781a32a581d43e3d512cf8ce714ecf04ea80f93ed0ff4a" +checksum = "d4a59a0cb1c7f84471ad5cd38d768c2a29390d17f1ff2827cdf49bc53e8ac70b" dependencies = [ "libc", "neli", @@ -2946,9 +2973,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", @@ -3187,9 +3214,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -3242,9 +3269,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -3260,9 +3287,9 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ "bitflags", "cfg-if", @@ -3292,9 +3319,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -3554,18 +3581,18 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -3582,7 +3609,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.40", + "zerocopy 0.8.48", ] [[package]] @@ -3633,11 +3660,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.10+spec-1.1.0", ] [[package]] @@ -3760,7 +3787,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.2", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -3769,9 +3796,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", @@ -3798,16 +3825,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3818,6 +3845,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "r2d2" version = "0.8.10" @@ -3841,9 +3874,9 @@ dependencies = [ [[package]] name = "r2d2_sqlite" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ebd03c29250cdf191da93a35118b4567c2ef0eacab54f65e058d6f4c9965f6" +checksum = "5576df16239e4e422c4835c8ed00be806d4491855c7847dba60b7aa8408b469b" dependencies = [ "r2d2", "rusqlite", @@ -3884,7 +3917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ "chacha20", - "getrandom 0.4.1", + "getrandom 0.4.2", "rand_core 0.10.0", ] @@ -4200,9 +4233,9 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3" +checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" dependencies = [ "bitflags", "fallible-iterator", @@ -4215,9 +4248,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" +checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" dependencies = [ "arrayvec", "borsh", @@ -4227,6 +4260,7 @@ dependencies = [ "rkyv", "serde", "serde_json", + "wasm-bindgen", ] [[package]] @@ -4237,9 +4271,9 @@ checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -4330,9 +4364,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" dependencies = [ "aws-lc-rs", "ring", @@ -4369,9 +4403,9 @@ checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -4446,9 +4480,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -4507,7 +4541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.13.0", + "indexmap 2.13.1", "itoa", "ryu", "serde_core", @@ -4519,7 +4553,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "itoa", "memchr", "serde", @@ -4560,9 +4594,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -4581,15 +4615,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.17.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.13.1", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -4600,11 +4634,11 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.17.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "darling 0.21.3", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.117", @@ -4659,9 +4693,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simdutf8" @@ -4699,12 +4733,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4885,12 +4919,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.26.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -4907,12 +4941,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4923,9 +4957,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c0624faaa317c56d6d19136580be889677259caf5c897941c6f446b4655068" +checksum = "0bd36b06a2a6c0c3c81a83be1ab05fe86460d054d4d51bf513bc56b3e15bdc22" dependencies = [ "astral-tokio-tar", "async-trait", @@ -5044,9 +5078,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -5064,9 +5098,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -5079,25 +5113,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -5156,13 +5190,13 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "serde_core", - "serde_spanned 1.0.4", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.15", ] [[package]] @@ -5183,39 +5217,48 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" dependencies = [ - "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "indexmap 2.13.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.1", ] [[package]] @@ -5226,9 +5269,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" @@ -5249,7 +5292,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2 0.6.2", + "socket2 0.6.3", "sync_wrapper", "tokio", "tokio-stream", @@ -5693,7 +5736,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.13.0", + "indexmap 2.13.1", "pin-project-lite", "slab", "sync_wrapper", @@ -5796,9 +5839,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "nu-ansi-term", "serde", @@ -5857,9 +5900,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -5887,9 +5930,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ "base64 0.22.1", "log", @@ -5897,14 +5940,14 @@ dependencies = [ "rustls", "rustls-pki-types", "ureq-proto", - "utf-8", + "utf8-zero", ] [[package]] name = "ureq-proto" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ "base64 0.22.1", "http", @@ -5926,10 +5969,10 @@ dependencies = [ ] [[package]] -name = "utf-8" -version = "0.7.6" +name = "utf8-zero" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" [[package]] name = "utf8_iter" @@ -5945,13 +5988,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", - "rand 0.9.2", + "rand 0.10.0", "wasm-bindgen", ] @@ -6024,36 +6067,33 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" dependencies = [ "cfg-if", "once_cell", "rustversion", + "serde", "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.64" +version = "0.4.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6061,9 +6101,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" dependencies = [ "bumpalo", "proc-macro2", @@ -6074,9 +6114,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" dependencies = [ "unicode-ident", ] @@ -6098,7 +6138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.0", + "indexmap 2.13.1", "wasm-encoder", "wasmparser", ] @@ -6111,15 +6151,15 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.13.1", "semver", ] [[package]] name = "web-sys" -version = "0.3.91" +version = "0.3.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" dependencies = [ "js-sys", "wasm-bindgen", @@ -6469,9 +6509,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" dependencies = [ "memchr", ] @@ -6504,7 +6553,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", - "indexmap 2.13.0", + "indexmap 2.13.1", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -6535,7 +6584,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "serde", "serde_derive", @@ -6554,7 +6603,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "semver", "serde", @@ -6566,9 +6615,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" @@ -6597,9 +6646,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -6608,9 +6657,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -6630,11 +6679,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ - "zerocopy-derive 0.8.40", + "zerocopy-derive 0.8.48", ] [[package]] @@ -6650,9 +6699,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", @@ -6661,18 +6710,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -6688,9 +6737,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -6699,9 +6748,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -6710,9 +6759,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", From 48e9606219dd27e69d1db8620be3dd754cb7a8c2 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 09:00:06 +0100 Subject: [PATCH 35/79] refactor: extract project dictionary from cSpell.json Move the project-specific word list from the inline 'words' array in cSpell.json into a dedicated project-words.txt dictionary file, following the same pattern used in other Torrust organisation repositories. Update packages/metrics/cSpell.json to reference the shared dictionary instead of maintaining its own inline word list. Closes #1484 --- cSpell.json | 217 +++-------------------------------- packages/metrics/cSpell.json | 26 ++--- project-words.txt | 199 ++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 214 deletions(-) create mode 100644 project-words.txt diff --git a/cSpell.json b/cSpell.json index 81421e050..43eb391d3 100644 --- a/cSpell.json +++ b/cSpell.json @@ -1,208 +1,23 @@ { - "words": [ - "Addrs", - "adduser", - "alekitto", - "appuser", - "Arvid", - "ASMS", - "asyn", - "autoclean", - "AUTOINCREMENT", - "automock", - "Avicora", - "Azureus", - "bdecode", - "bencode", - "bencoded", - "bencoding", - "beps", - "binascii", - "binstall", - "Bitflu", - "bools", - "Bragilevsky", - "bufs", - "buildid", - "Buildx", - "byteorder", - "callgrind", - "camino", - "canonicalize", - "canonicalized", - "certbot", - "chrono", - "Cinstrument", - "ciphertext", - "clippy", - "cloneable", - "codecov", - "codegen", - "completei", - "Condvar", - "connectionless", - "Containerfile", - "conv", - "curr", - "cvar", - "Cyberneering", - "dashmap", - "datagram", - "datetime", - "debuginfo", - "Deque", - "Dijke", - "distroless", - "dockerhub", - "downloadedi", - "dtolnay", - "elif", - "endianness", - "Eray", - "filesd", - "flamegraph", - "formatjson", - "Freebox", - "Frostegård", - "gecos", - "Gibibytes", - "Grcov", - "hasher", - "healthcheck", - "heaptrack", - "hexlify", - "hlocalhost", - "Hydranode", - "hyperthread", - "Icelake", - "iiiiiiiiiiiiiiiiiiiid", - "imdl", - "impls", - "incompletei", - "infohash", - "infohashes", - "infoschema", - "Intermodal", - "intervali", - "Joakim", - "kallsyms", - "Karatay", - "kcachegrind", - "kexec", - "keyout", - "Kibibytes", - "kptr", - "lcov", - "leecher", - "leechers", - "libsqlite", - "libtorrent", - "libz", - "LOGNAME", - "Lphant", - "matchmakes", - "Mebibytes", - "metainfo", - "middlewares", - "misresolved", - "mockall", - "multimap", - "myacicontext", - "ñaca", - "Naim", - "nanos", - "newkey", - "nextest", - "nocapture", - "nologin", - "nonroot", - "Norberg", - "numwant", - "nvCFlJCq7fz7Qx6KoKTDiMZvns8l5Kw7", - "oneshot", - "ostr", - "Pando", - "peekable", - "peerlist", - "programatik", - "proot", - "proto", - "Quickstart", - "Radeon", - "Rakshasa", - "Rasterbar", - "realpath", - "reannounce", - "Registar", - "repr", - "reqs", - "reqwest", - "rerequests", - "ringbuf", - "ringsize", - "rngs", - "rosegment", - "routable", - "rstest", - "rusqlite", - "rustc", - "RUSTDOCFLAGS", - "RUSTFLAGS", - "rustfmt", - "Rustls", - "Ryzen", - "Seedable", - "serde", - "Shareaza", - "sharktorrent", - "SHLVL", - "skiplist", - "slowloris", - "socketaddr", - "sqllite", - "subsec", - "Swatinem", - "Swiftbit", - "taiki", - "tdyne", - "Tebibytes", - "tempfile", - "testcontainers", - "thiserror", - "tlsv", - "Torrentstorm", - "torrust", - "torrustracker", - "trackerid", - "Trackon", - "typenum", - "udpv", - "Unamed", - "underflows", - "Unsendable", - "untuple", - "uroot", - "Vagaa", - "valgrind", - "Vitaly", - "vmlinux", - "Vuze", - "Weidendorfer", - "Werror", - "whitespaces", - "Xacrimon", - "XBTT", - "Xdebug", - "Xeon", - "Xtorrent", - "Xunlei", - "xxxxxxxxxxxxxxxxxxxxd", - "yyyyyyyyyyyyyyyyyyyyd", - "zerocopy" + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", + "version": "0.2", + "dictionaryDefinitions": [ + { + "name": "project-words", + "path": "./project-words.txt", + "addWords": true + } + ], + "dictionaries": [ + "project-words" ], "enableFiletypes": [ "dockerfile", "shellscript", "toml" + ], + "ignorePaths": [ + "target", + "/project-words.txt" ] -} +} \ No newline at end of file diff --git a/packages/metrics/cSpell.json b/packages/metrics/cSpell.json index f04cce9e3..8f5002833 100644 --- a/packages/metrics/cSpell.json +++ b/packages/metrics/cSpell.json @@ -1,21 +1,21 @@ { - "words": [ - "cloneable", - "formatjson", - "Gibibytes", - "Kibibytes", - "Mebibytes", - "ñaca", - "println", - "rstest", - "serde", - "subsec", - "Tebibytes", - "thiserror" + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", + "version": "0.2", + "dictionaryDefinitions": [ + { + "name": "project-words", + "path": "../../project-words.txt", + "addWords": true + } ], + "dictionaries": ["project-words"], "enableFiletypes": [ "dockerfile", "shellscript", "toml" + ], + "ignorePaths": [ + "target", + "/project-words.txt" ] } diff --git a/project-words.txt b/project-words.txt new file mode 100644 index 000000000..c698eea9c --- /dev/null +++ b/project-words.txt @@ -0,0 +1,199 @@ +Addrs +adduser +alekitto +appuser +Arvid +ASMS +asyn +autoclean +AUTOINCREMENT +automock +Avicora +Azureus +bdecode +bencode +bencoded +bencoding +beps +binascii +binstall +Bitflu +bools +Bragilevsky +bufs +buildid +Buildx +byteorder +callgrind +camino +canonicalize +canonicalized +certbot +chrono +Cinstrument +ciphertext +clippy +cloneable +codecov +codegen +completei +Condvar +connectionless +Containerfile +conv +curr +cvar +Cyberneering +dashmap +datagram +datetime +debuginfo +Deque +Dijke +distroless +dockerhub +downloadedi +dtolnay +elif +endianness +Eray +filesd +flamegraph +formatjson +Freebox +Frostegård +gecos +Gibibytes +Grcov +hasher +healthcheck +heaptrack +hexlify +hlocalhost +Hydranode +hyperthread +Icelake +iiiiiiiiiiiiiiiiiiiid +imdl +impls +incompletei +infohash +infohashes +infoschema +Intermodal +intervali +Joakim +kallsyms +Karatay +kcachegrind +kexec +keyout +Kibibytes +kptr +lcov +leecher +leechers +libsqlite +libtorrent +libz +LOGNAME +Lphant +matchmakes +Mebibytes +metainfo +middlewares +misresolved +mockall +multimap +myacicontext +ñaca +Naim +nanos +newkey +nextest +nocapture +nologin +nonroot +Norberg +numwant +nvCFlJCq7fz7Qx6KoKTDiMZvns8l5Kw7 +oneshot +ostr +Pando +peekable +peerlist +programatik +proot +proto +Quickstart +Radeon +Rakshasa +Rasterbar +realpath +reannounce +Registar +repr +reqs +reqwest +rerequests +ringbuf +ringsize +rngs +rosegment +routable +rstest +rusqlite +rustc +RUSTDOCFLAGS +RUSTFLAGS +rustfmt +Rustls +Ryzen +Seedable +serde +Shareaza +sharktorrent +SHLVL +skiplist +slowloris +socketaddr +sqllite +subsec +Swatinem +Swiftbit +taiki +tdyne +Tebibytes +tempfile +testcontainers +thiserror +tlsv +Torrentstorm +torrust +torrustracker +trackerid +Trackon +typenum +udpv +Unamed +underflows +Unsendable +untuple +uroot +Vagaa +valgrind +Vitaly +vmlinux +Vuze +Weidendorfer +Werror +whitespaces +Xacrimon +XBTT +Xdebug +Xeon +Xtorrent +Xunlei +xxxxxxxxxxxxxxxxxxxxd +yyyyyyyyyyyyyyyyyyyyd +zerocopy From c88f66cd42c733fafc5b7b4afeb862b7b3b28329 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:19:40 +0000 Subject: [PATCH 36/79] chore(deps): bump docker/login-action from 3 to 4 Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/container.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index 7416df71e..2f2b0780c 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -117,7 +117,7 @@ jobs: - id: login name: Login to Docker Hub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} @@ -158,7 +158,7 @@ jobs: - id: login name: Login to Docker Hub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} From 504135d009b2c16768ed13ce4b44ddf50b7d2f2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:19:47 +0000 Subject: [PATCH 37/79] chore(deps): bump docker/metadata-action from 5 to 6 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5...v6) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/container.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index 2f2b0780c..0615ad6be 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -108,7 +108,7 @@ jobs: steps: - id: meta name: Docker Meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | "${{ secrets.DOCKER_HUB_USERNAME }}/${{secrets.DOCKER_HUB_REPOSITORY_NAME }}" @@ -146,7 +146,7 @@ jobs: steps: - id: meta name: Docker Meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | "${{ secrets.DOCKER_HUB_USERNAME }}/${{secrets.DOCKER_HUB_REPOSITORY_NAME }}" From 2c78850ab49ede86f36f1d98f93f45b890b98895 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:19:32 +0000 Subject: [PATCH 38/79] chore(deps): bump docker/setup-buildx-action from 3 to 4 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/container.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index 0615ad6be..f09a94bca 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -26,7 +26,7 @@ jobs: steps: - id: setup name: Setup Toolchain - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - id: build name: Build @@ -124,7 +124,7 @@ jobs: - id: setup name: Setup Toolchain - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Build and push uses: docker/build-push-action@v6 @@ -165,7 +165,7 @@ jobs: - id: setup name: Setup Toolchain - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Build and push uses: docker/build-push-action@v6 From 4f3f1956f4a8d1839f95bd697b851ab04df31fbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:19:27 +0000 Subject: [PATCH 39/79] chore(deps): bump docker/build-push-action from 6 to 7 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6...v7) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/container.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index f09a94bca..e0857e936 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -30,7 +30,7 @@ jobs: - id: build name: Build - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: file: ./Containerfile push: false @@ -127,7 +127,7 @@ jobs: uses: docker/setup-buildx-action@v4 - name: Build and push - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: file: ./Containerfile push: true @@ -168,7 +168,7 @@ jobs: uses: docker/setup-buildx-action@v4 - name: Build and push - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: file: ./Containerfile push: true From f2612dc1fa0aa242503b0354227b644a12fbe47d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 12:34:06 +0100 Subject: [PATCH 40/79] docs(issue-523): add internal linting implementation plan --- docs/issues/523-internal-linting-tool.md | 141 +++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 docs/issues/523-internal-linting-tool.md diff --git a/docs/issues/523-internal-linting-tool.md b/docs/issues/523-internal-linting-tool.md new file mode 100644 index 000000000..14593e190 --- /dev/null +++ b/docs/issues/523-internal-linting-tool.md @@ -0,0 +1,141 @@ +# Issue #523 Implementation Plan (Internal Linting Tool) + +## Goal + +Replace the MegaLinter idea with Torrust internal linting tooling and integrate it into CI for this repository. + +## Scope + +- Target issue: https://github.com/torrust/torrust-tracker/issues/523 +- CI workflow to modify: .github/workflows/testing.yaml +- External reference workflow: https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.github/workflows/linting.yml + +## Tasks + +### 0) Create a local branch following GitHub branch naming conventions + +- Approved branch name: `523-internal-linting-tool` +- Commands: + - `git fetch --all --prune` + - `git checkout develop` + - `git pull --ff-only` + - `git checkout -b 523-internal-linting-tool` +- Checkpoint: + - `git branch --show-current` should output `523-internal-linting-tool`. + +### 1) Install and run the linting tool locally; verify it passes in this repo + +- Identify/install internal linting package/tool used by Torrust (likely `torrust-linting` or equivalent wrapper). +- Ensure local runtime dependencies are present (if any). +- Note: linter config files (step 2) must exist in the repo root before a full suite run; it is fine to do a first exploratory run first to discover which linters are active. +- Run the internal linting command against this repository. +- Capture the exact command and output summary for reproducibility. +- Checkpoint: + - Linting command exits with code `0`. + +### 2) Add and adapt linter configuration files + +Some linters require a config file in the repo root. Use the deployer configs as reference and adapt values to this repository. + +| File | Linter | Reference | +| -------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- | +| `.markdownlint.json` | markdownlint | https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.markdownlint.json | +| `.taplo.toml` | taplo (TOML fmt) | https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.taplo.toml | +| `.yamllint-ci.yml` | yamllint | https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.yamllint-ci.yml | + +Key adaptations to make per file: + +- `.markdownlint.json`: review line-length rules and Markdown conventions used in this repo's docs. +- `.taplo.toml`: update `exclude` list to match this repo's generated/runtime folders (e.g. `target/**`, `storage/**`) instead of the deployer-specific ones (`build/**`, `data/**`, `envs/**`). +- `.yamllint-ci.yml`: update `ignore` block to reflect this repo's generated/runtime directories instead of cloud-init and deployer folders. + +Commit message: `ci(lint): add linter config files (.markdownlint.json, .taplo.toml, .yamllint-ci.yml)` + +Checkpoint: + +- Config files are present in the repo root. +- Running each individual linter against the repo with the config produces expected/controlled output. + +### 3) If local linting fails, fix all lint errors; commit fixes independently per linter + +- If the linting suite reports failures: + - Group findings by linter (for example: formatting, clippy, docs, spelling, yaml, etc.). + - Fix only one linter category at a time. + - Create one commit per linter category. +- Commit style proposal: + - `fix(lint/): resolve ` +- Constraints: + - Do not mix workflow/tooling changes with source lint fixes in the same commit. + - Keep each commit minimal and reviewable. +- Checkpoint: + - Re-run linting suite; all checks pass before moving to workflow integration. + +### 4) Review existing workflow example using internal linting + +- Read and analyze: + - https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.github/workflows/linting.yml +- Extract and adapt: + - Trigger strategy. + - Tool setup/install method. + - Cache strategy. + - Invocation command and CI fail behavior. +- Checkpoint: + - Document a short mapping from deployer workflow pattern to this repo’s `testing.yaml` job structure. + +### 5) Modify `.github/workflows/testing.yaml` to use the internal linting tool + +- Update the current `check`/lint-related section to run the internal linting command. +- Replace existing lint/check execution path with the internal linting tool in this migration (no parallel transition mode). +- Ensure matrix/toolchain compatibility is explicit (nightly/stable behavior decided and documented). +- Validate workflow syntax before commit. +- Checkpoint: + - Workflow is valid and executes linting through internal tool. + +### 6) Commit workflow changes + +- Commit only workflow-related changes in a dedicated commit. +- Commit message proposal: + - `ci(lint): switch testing workflow to internal linting tool` +- Checkpoint: + - `git show --name-only --stat HEAD` includes only expected workflow files (and any required supporting CI files if intentionally added). + +### 7) Push to remote `josecelano` and open PR into `develop` + +- Verify remote exists: + - `git remote -v` +- Push branch: + - `git push -u josecelano 523-internal-linting-tool` +- Open PR targeting `torrust/torrust-tracker:develop` with head `josecelano:523-internal-linting-tool`. +- PR content should include: + - Why internal linting over MegaLinter. + - Summary of lint-fix commits by linter. + - Summary of workflow change. + - Evidence (local run + CI status). +- Checkpoint: + - PR is open, linked to issue #523, and ready for review. + +## Execution Notes + +- Keep PR review-friendly by separating commits by concern: + 1. Linter config files (step 2) + 2. Per-linter source fixes (step 3, only if needed) + 3. CI workflow migration (step 6) +- Use Conventional Commits for all commits in this implementation. +- If lint checks differ between local and CI, align tool versions and execution flags before merging. +- Avoid broad refactors unrelated to lint failures. + +## Decisions Confirmed + +1. Branch name: `523-internal-linting-tool`. +2. CI strategy: replace existing lint/check path with internal linting. +3. Commit convention: yes, use Conventional Commits. +4. PR target: base `torrust/torrust-tracker:develop`, head `josecelano:523-internal-linting-tool`. + +## Risks and Mitigations + +- Risk: Internal linting wrapper may not be version-pinned and may produce unstable CI behavior. + - Mitigation: Pin tool version in workflow installation step. +- Risk: Internal linting may overlap with existing checks, increasing CI time. + - Mitigation: Remove redundant jobs only after verifying coverage parity. +- Risk: Tool may require secrets or environment assumptions not available in CI. + - Mitigation: Run dry-run in GitHub Actions on branch before requesting review. From fa3b491bb70348be86bc51f80431ece411596554 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:00:55 +0100 Subject: [PATCH 41/79] ci(lint): add linter config files --- .markdownlint.json | 18 ++++++++++++++++++ .taplo.toml | 31 +++++++++++++++++++++++++++++++ .yamllint-ci.yml | 16 ++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 .markdownlint.json create mode 100644 .taplo.toml create mode 100644 .yamllint-ci.yml diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..19ec47c2e --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,18 @@ +{ + "default": true, + "MD013": false, + "MD031": true, + "MD032": true, + "MD040": true, + "MD022": true, + "MD009": true, + "MD007": { + "indent": 2 + }, + "MD026": false, + "MD041": false, + "MD034": false, + "MD024": false, + "MD033": false, + "MD060": false +} diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 000000000..d0f755dcd --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,31 @@ +# Taplo configuration file for TOML formatting +# Used by the "Even Better TOML" VS Code extension + +# Exclude generated and runtime folders from linting +exclude = [ + "target/**", + "storage/**", + ".coverage/**", +] + +[formatting] +# Preserve blank lines that exist +allowed_blank_lines = 1 +# Don't reorder keys to maintain structure +reorder_keys = false +# Array formatting +array_trailing_comma = true +array_auto_expand = false +array_auto_collapse = false +# Inline table formatting +inline_table_expand = false +compact_inline_tables = false +compact_arrays = false +# Alignment +align_entries = false +align_comments = true +# Indentation +indent_tables = false +indent_entries = false +# Other +trailing_newline = true diff --git a/.yamllint-ci.yml b/.yamllint-ci.yml new file mode 100644 index 000000000..9380b592a --- /dev/null +++ b/.yamllint-ci.yml @@ -0,0 +1,16 @@ +extends: default + +rules: + line-length: + max: 200 # More reasonable for infrastructure code + comments: + min-spaces-from-content: 1 # Allow single space before comments + document-start: disable # Most project YAML files don't require --- + truthy: + allowed-values: ["true", "false", "yes", "no", "on", "off"] # Allow common GitHub Actions values + +# Ignore generated/runtime directories +ignore: | + target/** + storage/** + .coverage/** From bc1f8cc72c0f8752480321860262a4e04f14305f Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:09:21 +0100 Subject: [PATCH 42/79] fix(lint/clippy): resolve pedantic duration and style violations --- packages/axum-rest-tracker-api-server/src/server.rs | 4 ++-- .../benches/http_tracker_core_benchmark.rs | 2 +- .../benches/repository_benchmark.rs | 8 ++++---- .../torrent-repository-benchmarking/tests/entry/mod.rs | 5 +++-- .../tests/repository/mod.rs | 5 +++-- packages/tracker-client/src/udp/client.rs | 2 +- .../benches/udp_tracker_core_benchmark.rs | 2 +- packages/udp-tracker-server/src/server/launcher.rs | 2 +- packages/udp-tracker-server/src/statistics/repository.rs | 4 ++-- packages/udp-tracker-server/tests/server/contract.rs | 2 +- 10 files changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/axum-rest-tracker-api-server/src/server.rs b/packages/axum-rest-tracker-api-server/src/server.rs index 05adeae8a..9eef6b71a 100644 --- a/packages/axum-rest-tracker-api-server/src/server.rs +++ b/packages/axum-rest-tracker-api-server/src/server.rs @@ -220,9 +220,9 @@ pub struct Launcher { impl std::fmt::Display for Launcher { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.tls.is_some() { - write!(f, "(with socket): {}, using TLS", self.bind_to,) + write!(f, "(with socket): {}, using TLS", self.bind_to) } else { - write!(f, "(with socket): {}, without TLS", self.bind_to,) + write!(f, "(with socket): {}, without TLS", self.bind_to) } } } diff --git a/packages/http-tracker-core/benches/http_tracker_core_benchmark.rs b/packages/http-tracker-core/benches/http_tracker_core_benchmark.rs index aa50ceeb9..c193c5124 100644 --- a/packages/http-tracker-core/benches/http_tracker_core_benchmark.rs +++ b/packages/http-tracker-core/benches/http_tracker_core_benchmark.rs @@ -12,7 +12,7 @@ fn announce_once(c: &mut Criterion) { let mut group = c.benchmark_group("http_tracker_handle_announce_once"); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("handle_announce_data", |b| { b.iter(|| sync::return_announce_data_once(100)); diff --git a/packages/torrent-repository-benchmarking/benches/repository_benchmark.rs b/packages/torrent-repository-benchmarking/benches/repository_benchmark.rs index a58207492..f5f8e4b28 100644 --- a/packages/torrent-repository-benchmarking/benches/repository_benchmark.rs +++ b/packages/torrent-repository-benchmarking/benches/repository_benchmark.rs @@ -17,7 +17,7 @@ fn add_one_torrent(c: &mut Criterion) { let mut group = c.benchmark_group("add_one_torrent"); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("RwLockStd", |b| { b.iter_custom(sync::add_one_torrent::); @@ -74,7 +74,7 @@ fn add_multiple_torrents_in_parallel(c: &mut Criterion) { //group.sample_size(10); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("RwLockStd", |b| { b.to_async(&rt) @@ -138,7 +138,7 @@ fn update_one_torrent_in_parallel(c: &mut Criterion) { //group.sample_size(10); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("RwLockStd", |b| { b.to_async(&rt) @@ -202,7 +202,7 @@ fn update_multiple_torrents_in_parallel(c: &mut Criterion) { //group.sample_size(10); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("RwLockStd", |b| { b.to_async(&rt) diff --git a/packages/torrent-repository-benchmarking/tests/entry/mod.rs b/packages/torrent-repository-benchmarking/tests/entry/mod.rs index 5cbb3b19c..86ca891d4 100644 --- a/packages/torrent-repository-benchmarking/tests/entry/mod.rs +++ b/packages/torrent-repository-benchmarking/tests/entry/mod.rs @@ -1,5 +1,4 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::ops::Sub; use std::time::Duration; use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes}; @@ -430,7 +429,9 @@ async fn it_should_remove_inactive_peers_beyond_cutoff( let now = clock::Working::now(); clock::Stopped::local_set(&now); - peer.updated = now.sub(EXPIRE); + peer.updated = now + .checked_sub(EXPIRE) + .expect("it_should_remove_inactive_peers_beyond_cutoff: EXPIRE must not exceed now"); torrent.upsert_peer(&peer).await; diff --git a/packages/torrent-repository-benchmarking/tests/repository/mod.rs b/packages/torrent-repository-benchmarking/tests/repository/mod.rs index ec7e68bae..fb0b8fcff 100644 --- a/packages/torrent-repository-benchmarking/tests/repository/mod.rs +++ b/packages/torrent-repository-benchmarking/tests/repository/mod.rs @@ -526,7 +526,6 @@ async fn it_should_remove_inactive_peers( repo: Repo, #[case] entries: Entries, ) { - use std::ops::Sub as _; use std::time::Duration; use torrust_tracker_clock::clock::stopped::Stopped as _; @@ -556,7 +555,9 @@ async fn it_should_remove_inactive_peers( let now = clock::Working::now(); clock::Stopped::local_set(&now); - peer.updated = now.sub(EXPIRE); + peer.updated = now + .checked_sub(EXPIRE) + .expect("it_should_remove_inactive_peers_beyond_cutoff: EXPIRE must not exceed now"); } // Insert the infohash and peer into the repository diff --git a/packages/tracker-client/src/udp/client.rs b/packages/tracker-client/src/udp/client.rs index 1c5ffd901..94c882d29 100644 --- a/packages/tracker-client/src/udp/client.rs +++ b/packages/tracker-client/src/udp/client.rs @@ -256,7 +256,7 @@ pub async fn check(service_binding: &ServiceBinding) -> Result { } }; - let sleep = time::sleep(Duration::from_millis(2000)); + let sleep = time::sleep(Duration::from_secs(2)); tokio::pin!(sleep); tokio::select! { diff --git a/packages/udp-tracker-core/benches/udp_tracker_core_benchmark.rs b/packages/udp-tracker-core/benches/udp_tracker_core_benchmark.rs index 5bd0e27c8..90fc721d0 100644 --- a/packages/udp-tracker-core/benches/udp_tracker_core_benchmark.rs +++ b/packages/udp-tracker-core/benches/udp_tracker_core_benchmark.rs @@ -9,7 +9,7 @@ use crate::helpers::sync; fn bench_connect_once(c: &mut Criterion) { let mut group = c.benchmark_group("udp_tracker/connect_once"); group.warm_up_time(Duration::from_millis(500)); - group.measurement_time(Duration::from_millis(1000)); + group.measurement_time(Duration::from_secs(1)); group.bench_function("connect_once", |b| { b.iter(|| sync::connect_once(100)); diff --git a/packages/udp-tracker-server/src/server/launcher.rs b/packages/udp-tracker-server/src/server/launcher.rs index a514921cc..4fd3a95d9 100644 --- a/packages/udp-tracker-server/src/server/launcher.rs +++ b/packages/udp-tracker-server/src/server/launcher.rs @@ -54,7 +54,7 @@ impl Launcher { panic!("it should not use udp if using authentication"); } - let socket = tokio::time::timeout(Duration::from_millis(5000), BoundSocket::new(bind_to)) + let socket = tokio::time::timeout(Duration::from_secs(5), BoundSocket::new(bind_to)) .await .expect("it should bind to the socket within five seconds"); diff --git a/packages/udp-tracker-server/src/statistics/repository.rs b/packages/udp-tracker-server/src/statistics/repository.rs index 94a86e3ab..c4c995b8a 100644 --- a/packages/udp-tracker-server/src/statistics/repository.rs +++ b/packages/udp-tracker-server/src/statistics/repository.rs @@ -330,7 +330,7 @@ mod tests { // Calculate new average with processing time of 2000ns // This will increment the processed requests counter from 0 to 1 - let processing_time = Duration::from_nanos(2000); + let processing_time = Duration::from_micros(2); let new_avg = repo .recalculate_udp_avg_processing_time_ns(processing_time, &connect_labels, now) .await; @@ -417,7 +417,7 @@ mod tests { let now = CurrentClock::now(); // Test with zero connections (should not panic, should handle division by zero) - let processing_time = Duration::from_nanos(1000); + let processing_time = Duration::from_micros(1); let connect_labels = LabelSet::from([("request_kind", "connect")]); let connect_avg = repo diff --git a/packages/udp-tracker-server/tests/server/contract.rs b/packages/udp-tracker-server/tests/server/contract.rs index e9691c879..350f3b8eb 100644 --- a/packages/udp-tracker-server/tests/server/contract.rs +++ b/packages/udp-tracker-server/tests/server/contract.rs @@ -32,7 +32,7 @@ async fn send_connection_request(transaction_id: TransactionId, client: &UdpTrac match response { Response::Connect(connect_response) => connect_response.connection_id, - _ => panic!("error connecting to udp server {:?}", response), + _ => panic!("error connecting to udp server {response:?}"), } } From f9b59f0c8e3dfbc0d79c0b43efbb10b95a157a6d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:29:05 +0100 Subject: [PATCH 43/79] fix(lint/cspell): configure ignores and dictionary for repo --- .github/workflows/upload_coverage_pr.yaml | 2 +- cspell.json | 27 ++++++++++++ project-words.txt | 53 +++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 cspell.json diff --git a/.github/workflows/upload_coverage_pr.yaml b/.github/workflows/upload_coverage_pr.yaml index 8b0006a6d..55de02c62 100644 --- a/.github/workflows/upload_coverage_pr.yaml +++ b/.github/workflows/upload_coverage_pr.yaml @@ -1,7 +1,7 @@ name: Upload Coverage Report (PR) on: - # This workflow is triggered after every successfull execution + # This workflow is triggered after every successful execution # of `Generate Coverage Report` workflow. workflow_run: workflows: ["Generate Coverage Report (PR)"] diff --git a/cspell.json b/cspell.json new file mode 100644 index 000000000..02f29f7f9 --- /dev/null +++ b/cspell.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", + "version": "0.2", + "dictionaryDefinitions": [ + { + "name": "project-words", + "path": "./project-words.txt", + "addWords": true + } + ], + "dictionaries": [ + "project-words" + ], + "enableFiletypes": [ + "dockerfile", + "shellscript", + "toml" + ], + "ignorePaths": [ + "target", + "docs/media/*.svg", + "contrib/bencode/benches/*.bencode", + "contrib/dev-tools/su-exec/**", + ".github/labels.json", + "/project-words.txt" + ] +} \ No newline at end of file diff --git a/project-words.txt b/project-words.txt index c698eea9c..48c9565cc 100644 --- a/project-words.txt +++ b/project-words.txt @@ -197,3 +197,56 @@ Xunlei xxxxxxxxxxxxxxxxxxxxd yyyyyyyyyyyyyyyyyyyyd zerocopy +Aideq +autoremove +CALLSITE +Dihc +Dmqcd +QJSF +Glrg +Irwe +Uninit +Unparker +eventfd +fastrand +fdbased +fdget +fput +iiiiiiiiiiiiiiiippe +iiiiiiiiiiiiiiiipp +iiiiiiiiiiiiiiip +iipp +iiiipp +jdbe +ksys +llist +mmap +mprotect +nonblocking +peersld +pkey +porti +prealloc +println +shellcheck +sockfd +subkey +sysmalloc +sysret +timespec +toki +torru +ttwu +uninit +unparked +unsync +vtable +wakelist +wakeup +actix +iterationsadd +josecelano +mysqladmin +setgroups +taplo +trixie From b654fa5fb18ffa94d167aef3e21becfdac7fbda7 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:40:03 +0100 Subject: [PATCH 44/79] fix(lint/markdown): resolve markdownlint violations --- README.md | 18 ++++-------------- contrib/bencode/README.md | 3 ++- contrib/dev-tools/su-exec/README.md | 4 ++-- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index bb102355b..2fe28db08 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Others: ## Implemented BitTorrent Enhancement Proposals (BEPs) -> + > _[Learn more about BitTorrent Enhancement Proposals][BEP 00]_ - [BEP 03]: The BitTorrent Protocol. @@ -113,8 +113,8 @@ podman run -it docker.io/torrust/tracker:develop ### Development Version -- Please ensure you have the _**[latest stable (or nightly) version of rust][rust]___. -- Please ensure that your computer has enough RAM. _**Recommended 16GB.___ +- Please ensure you have the \_\*\*[latest stable (or nightly) version of rust][rust]\_\_\_. +- Please ensure that your computer has enough RAM. \_\*\*Recommended 16GB.\_\_\_ #### Checkout, Test and Run @@ -217,7 +217,7 @@ This program is free software: you can redistribute it and/or modify it under th This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [GNU Affero General Public License][AGPL_3_0] for more details. -You should have received a copy of the *GNU Affero General Public License* along with this program. If not, see . +You should have received a copy of the _GNU Affero General Public License_ along with this program. If not, see . Some files include explicit copyright notices and/or license notices. @@ -250,18 +250,14 @@ This project was a joint effort by [Nautilus Cyberneering GmbH][nautilus] and [D [deployment_wf_b]: ../../actions/workflows/deployment.yaml/badge.svg [testing_wf]: ../../actions/workflows/testing.yaml [testing_wf_b]: ../../actions/workflows/testing.yaml/badge.svg - [bittorrent]: http://bittorrent.org/ [rust]: https://www.rust-lang.org/ [axum]: https://github.com/tokio-rs/axum [newtrackon]: https://newtrackon.com/ [coverage]: https://app.codecov.io/gh/torrust/torrust-tracker [torrust]: https://torrust.com/ - [dockerhub]: https://hub.docker.com/r/torrust/tracker/tags - [torrent_source_felid]: https://github.com/qbittorrent/qBittorrent/discussions/19406 - [BEP 00]: https://www.bittorrent.org/beps/bep_0000.html [BEP 03]: https://www.bittorrent.org/beps/bep_0003.html [BEP 07]: https://www.bittorrent.org/beps/bep_0007.html @@ -269,24 +265,18 @@ This project was a joint effort by [Nautilus Cyberneering GmbH][nautilus] and [D [BEP 23]: https://www.bittorrent.org/beps/bep_0023.html [BEP 27]: https://www.bittorrent.org/beps/bep_0027.html [BEP 48]: https://www.bittorrent.org/beps/bep_0048.html - [containers.md]: ./docs/containers.md - [docs]: https://docs.rs/torrust-tracker/latest/ [api]: https://docs.rs/torrust-tracker/latest/torrust_tracker/servers/apis/v1 [http]: https://docs.rs/torrust-tracker/latest/torrust_tracker/servers/http [udp]: https://docs.rs/torrust-tracker/latest/torrust_tracker/servers/udp - [good first issues]: https://github.com/torrust/torrust-tracker/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22 [discussions]: https://github.com/torrust/torrust-tracker/discussions - [guide.md]: https://github.com/torrust/.github/blob/main/info/contributing.md [agreement.md]: https://github.com/torrust/.github/blob/main/info/licensing/contributor_agreement_v01.md - [AGPL_3_0]: ./docs/licenses/LICENSE-AGPL_3_0 [MIT_0]: ./docs/licenses/LICENSE-MIT_0 [FSF]: https://www.fsf.org/ - [nautilus]: https://github.com/orgs/Nautilus-Cyberneering/ [Dutch Bits]: https://dutchbits.nl [Naim A.]: https://github.com/naim94a/udpt diff --git a/contrib/bencode/README.md b/contrib/bencode/README.md index 7a203082b..81c09f691 100644 --- a/contrib/bencode/README.md +++ b/contrib/bencode/README.md @@ -1,4 +1,5 @@ # Bencode + This library allows for the creation and parsing of bencode encodings. -Bencode is the binary encoding used throughout bittorrent technologies from metainfo files to DHT messages. Bencode types include integers, byte arrays, lists, and dictionaries, of which the last two can hold any bencode type (they could be recursively constructed). \ No newline at end of file +Bencode is the binary encoding used throughout bittorrent technologies from metainfo files to DHT messages. Bencode types include integers, byte arrays, lists, and dictionaries, of which the last two can hold any bencode type (they could be recursively constructed). diff --git a/contrib/dev-tools/su-exec/README.md b/contrib/dev-tools/su-exec/README.md index 2b0517377..1dd4108ac 100644 --- a/contrib/dev-tools/su-exec/README.md +++ b/contrib/dev-tools/su-exec/README.md @@ -1,4 +1,5 @@ # su-exec + switch user and group id, setgroups and exec ## Purpose @@ -21,7 +22,7 @@ name separated with colon (e.g. `nobody:ftp`). Numeric uid/gid values can be used instead of names. Example: ```shell -$ su-exec apache:1000 /usr/sbin/httpd -f /opt/www/httpd.conf +su-exec apache:1000 /usr/sbin/httpd -f /opt/www/httpd.conf ``` ## TTY & parent/child handling @@ -43,4 +44,3 @@ PID USER TIME COMMAND This does more or less exactly the same thing as [gosu](https://github.com/tianon/gosu) but it is only 10kb instead of 1.8MB. - From 0e174af960b966e3a6a8d1b69fd306a4fbc07b83 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:53:14 +0100 Subject: [PATCH 45/79] fix(lint/yaml): resolve workflow yamllint issues --- .github/workflows/container.yaml | 10 ++++++++-- .github/workflows/coverage.yaml | 4 ++-- .github/workflows/generate_coverage_pr.yaml | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index e0857e936..7e8ffa442 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -80,9 +80,15 @@ jobs: echo "continue=true" >> $GITHUB_OUTPUT echo "On \`develop\` Branch, Type: \`development\`" - elif [[ $(echo "${{ github.ref }}" | grep -P '^(refs\/heads\/releases\/)(v)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$') ]]; then + elif [[ "${{ github.ref }}" =~ ^refs/heads/releases/ ]]; then + semver_regex='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' + version=$(echo "${{ github.ref }}" | sed -n -E 's#^refs/heads/releases/##p') + + if [[ ! "$version" =~ $semver_regex ]]; then + echo "Not a valid release branch semver. Will Not Continue" + exit 0 + fi - version=$(echo "${{ github.ref }}" | sed -n -E 's/^(refs\/heads\/releases\/)//p') echo "version=$version" >> $GITHUB_OUTPUT echo "type=release" >> $GITHUB_OUTPUT echo "continue=true" >> $GITHUB_OUTPUT diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 2c8d63d6c..4c49217c2 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -44,7 +44,7 @@ jobs: - id: coverage name: Generate Coverage Report run: | - cargo clean + cargo clean cargo llvm-cov --all-features --workspace --codecov --output-path ./codecov.json - id: upload @@ -54,4 +54,4 @@ jobs: verbose: true token: ${{ secrets.CODECOV_TOKEN }} files: ${{ github.workspace }}/codecov.json - fail_ci_if_error: true \ No newline at end of file + fail_ci_if_error: true diff --git a/.github/workflows/generate_coverage_pr.yaml b/.github/workflows/generate_coverage_pr.yaml index a3f97dbf2..e07a5a755 100644 --- a/.github/workflows/generate_coverage_pr.yaml +++ b/.github/workflows/generate_coverage_pr.yaml @@ -44,7 +44,7 @@ jobs: - id: coverage name: Generate Coverage Report run: | - cargo clean + cargo clean cargo llvm-cov --all-features --workspace --codecov --output-path ./codecov.json - name: Store PR number and commit SHA From 7085250ee5033b6ed62dfdf92e4c2c57256dbb85 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:55:12 +0100 Subject: [PATCH 46/79] fix(lint/toml): normalize taplo formatting across workspace --- .cargo/config.toml | 32 +++++++++---------- .taplo.toml | 18 ++++------- Cargo.toml | 24 +++++++------- console/tracker-client/Cargo.toml | 18 +++++------ contrib/bencode/Cargo.toml | 4 +-- .../axum-health-check-api-server/Cargo.toml | 18 +++++------ packages/axum-http-tracker-server/Cargo.toml | 20 ++++++------ .../axum-rest-tracker-api-server/Cargo.toml | 28 ++++++++-------- packages/axum-server/Cargo.toml | 12 +++---- packages/clock/Cargo.toml | 4 +-- packages/configuration/Cargo.toml | 16 +++++----- packages/events/Cargo.toml | 4 +-- packages/http-protocol/Cargo.toml | 6 ++-- packages/http-tracker-core/Cargo.toml | 6 ++-- packages/located-error/Cargo.toml | 2 +- packages/metrics/Cargo.toml | 8 ++--- packages/primitives/Cargo.toml | 6 ++-- packages/rest-tracker-api-client/Cargo.toml | 10 +++--- packages/rest-tracker-api-core/Cargo.toml | 4 +-- packages/server-lib/Cargo.toml | 8 ++--- .../swarm-coordination-registry/Cargo.toml | 12 +++---- packages/test-helpers/Cargo.toml | 4 +-- .../Cargo.toml | 8 ++--- packages/tracker-client/Cargo.toml | 12 +++---- packages/tracker-core/Cargo.toml | 14 ++++---- packages/udp-protocol/Cargo.toml | 2 +- packages/udp-tracker-core/Cargo.toml | 6 ++-- packages/udp-tracker-server/Cargo.toml | 10 +++--- 28 files changed, 156 insertions(+), 160 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 28cde74ec..36a0b3d8c 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -7,20 +7,20 @@ time = "build --timings --all-targets" [build] rustflags = [ - "-D", - "warnings", - "-D", - "future-incompatible", - "-D", - "let-underscore", - "-D", - "nonstandard-style", - "-D", - "rust-2018-compatibility", - "-D", - "rust-2018-idioms", - "-D", - "rust-2021-compatibility", - "-D", - "unused", + "-D", + "warnings", + "-D", + "future-incompatible", + "-D", + "let-underscore", + "-D", + "nonstandard-style", + "-D", + "rust-2018-compatibility", + "-D", + "rust-2018-idioms", + "-D", + "rust-2021-compatibility", + "-D", + "unused", ] diff --git a/.taplo.toml b/.taplo.toml index d0f755dcd..0168711e8 100644 --- a/.taplo.toml +++ b/.taplo.toml @@ -2,11 +2,7 @@ # Used by the "Even Better TOML" VS Code extension # Exclude generated and runtime folders from linting -exclude = [ - "target/**", - "storage/**", - ".coverage/**", -] +exclude = [ ".coverage/**", "storage/**", "target/**" ] [formatting] # Preserve blank lines that exist @@ -14,18 +10,18 @@ allowed_blank_lines = 1 # Don't reorder keys to maintain structure reorder_keys = false # Array formatting -array_trailing_comma = true -array_auto_expand = false array_auto_collapse = false +array_auto_expand = false +array_trailing_comma = true # Inline table formatting -inline_table_expand = false -compact_inline_tables = false compact_arrays = false +compact_inline_tables = false +inline_table_expand = false # Alignment -align_entries = false align_comments = true +align_entries = false # Indentation -indent_tables = false indent_entries = false +indent_tables = false # Other trailing_newline = true diff --git a/Cargo.toml b/Cargo.toml index dbc39bdf8..1eb5f0d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,13 +19,13 @@ version.workspace = true name = "torrust_tracker_lib" [workspace.package] -authors = ["Nautilus Cyberneering , Mick van Dijke "] -categories = ["network-programming", "web-programming"] +authors = [ "Nautilus Cyberneering , Mick van Dijke " ] +categories = [ "network-programming", "web-programming" ] description = "A feature rich BitTorrent tracker." documentation = "https://docs.rs/crate/torrust-tracker/" edition = "2021" homepage = "https://torrust.com/" -keywords = ["bittorrent", "file-sharing", "peer-to-peer", "torrent", "tracker"] +keywords = [ "bittorrent", "file-sharing", "peer-to-peer", "torrent", "tracker" ] license = "AGPL-3.0-only" publish = true repository = "https://github.com/torrust/torrust-tracker" @@ -34,19 +34,19 @@ version = "3.0.0-develop" [dependencies] anyhow = "1" -axum-server = { version = "0", features = ["tls-rustls-no-provider"] } +axum-server = { version = "0", features = [ "tls-rustls-no-provider" ] } bittorrent-http-tracker-core = { version = "3.0.0-develop", path = "packages/http-tracker-core" } bittorrent-tracker-core = { version = "3.0.0-develop", path = "packages/tracker-core" } bittorrent-udp-tracker-core = { version = "3.0.0-develop", path = "packages/udp-tracker-core" } -chrono = { version = "0", default-features = false, features = ["clock"] } -clap = { version = "4", features = ["derive", "env"] } +chrono = { version = "0", default-features = false, features = [ "clock" ] } +clap = { version = "4", features = [ "derive", "env" ] } rand = "0" regex = "1" -reqwest = { version = "0", features = ["json"] } -serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["preserve_order"] } +reqwest = { version = "0", features = [ "json" ] } +serde = { version = "1", features = [ "derive" ] } +serde_json = { version = "1", features = [ "preserve_order" ] } thiserror = "2.0.12" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-axum-health-check-api-server = { version = "3.0.0-develop", path = "packages/axum-health-check-api-server" } torrust-axum-http-tracker-server = { version = "3.0.0-develop", path = "packages/axum-http-tracker-server" } @@ -59,7 +59,7 @@ torrust-tracker-configuration = { version = "3.0.0-develop", path = "packages/co torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "packages/swarm-coordination-registry" } torrust-udp-tracker-server = { version = "3.0.0-develop", path = "packages/udp-tracker-server" } tracing = "0" -tracing-subscriber = { version = "0", features = ["json"] } +tracing-subscriber = { version = "0", features = [ "json" ] } [dev-dependencies] bittorrent-primitives = "0.1.0" @@ -70,7 +70,7 @@ torrust-rest-tracker-api-client = { version = "3.0.0-develop", path = "packages/ torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "packages/test-helpers" } [workspace] -members = ["console/tracker-client", "packages/torrent-repository-benchmarking"] +members = [ "console/tracker-client", "packages/torrent-repository-benchmarking" ] [profile.dev] debug = 1 diff --git a/console/tracker-client/Cargo.toml b/console/tracker-client/Cargo.toml index d4ab7c9e3..8c12227e9 100644 --- a/console/tracker-client/Cargo.toml +++ b/console/tracker-client/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A collection of console clients to make requests to BitTorrent trackers." -keywords = ["bittorrent", "client", "tracker"] +keywords = [ "bittorrent", "client", "tracker" ] license = "LGPL-3.0" name = "torrust-tracker-client" readme = "README.md" @@ -19,21 +19,21 @@ anyhow = "1" aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" bittorrent-tracker-client = { version = "3.0.0-develop", path = "../../packages/tracker-client" } -clap = { version = "4", features = ["derive", "env"] } +clap = { version = "4", features = [ "derive", "env" ] } futures = "0" hex-literal = "1" hyper = "1" -reqwest = { version = "0", features = ["json"] } -serde = { version = "1", features = ["derive"] } +reqwest = { version = "0", features = [ "json" ] } +serde = { version = "1", features = [ "derive" ] } serde_bencode = "0" serde_bytes = "0" -serde_json = { version = "1", features = ["preserve_order"] } +serde_json = { version = "1", features = [ "preserve_order" ] } thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../../packages/configuration" } tracing = "0" -tracing-subscriber = { version = "0", features = ["json"] } -url = { version = "2", features = ["serde"] } +tracing-subscriber = { version = "0", features = [ "json" ] } +url = { version = "2", features = [ "serde" ] } [package.metadata.cargo-machete] -ignored = ["serde_bytes"] +ignored = [ "serde_bytes" ] diff --git a/contrib/bencode/Cargo.toml b/contrib/bencode/Cargo.toml index f6355b6fc..5fab1792d 100644 --- a/contrib/bencode/Cargo.toml +++ b/contrib/bencode/Cargo.toml @@ -1,10 +1,10 @@ [package] description = "(contrib) Efficient decoding and encoding for bencode." -keywords = ["bencode", "contrib", "library"] +keywords = [ "bencode", "contrib", "library" ] name = "torrust-tracker-contrib-bencode" readme = "README.md" -authors = ["Nautilus Cyberneering , Andrew "] +authors = [ "Nautilus Cyberneering , Andrew " ] license = "Apache-2.0" repository = "https://github.com/torrust/bittorrent-infrastructure-project" diff --git a/packages/axum-health-check-api-server/Cargo.toml b/packages/axum-health-check-api-server/Cargo.toml index e0504f7df..cf9d8d9a3 100644 --- a/packages/axum-health-check-api-server/Cargo.toml +++ b/packages/axum-health-check-api-server/Cargo.toml @@ -4,7 +4,7 @@ description = "The Torrust Bittorrent HTTP tracker." documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["axum", "bittorrent", "healthcheck", "http", "server", "torrust", "tracker"] +keywords = [ "axum", "bittorrent", "healthcheck", "http", "server", "torrust", "tracker" ] license.workspace = true name = "torrust-axum-health-check-api-server" publish.workspace = true @@ -14,27 +14,27 @@ rust-version.workspace = true version.workspace = true [dependencies] -axum = { version = "0", features = ["macros"] } -axum-server = { version = "0", features = ["tls-rustls-no-provider"] } +axum = { version = "0", features = [ "macros" ] } +axum-server = { version = "0", features = [ "tls-rustls-no-provider" ] } futures = "0" hyper = "1" -serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["preserve_order"] } -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +serde = { version = "1", features = [ "derive" ] } +serde_json = { version = "1", features = [ "preserve_order" ] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-axum-server = { version = "3.0.0-develop", path = "../axum-server" } torrust-server-lib = { version = "3.0.0-develop", path = "../server-lib" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } -tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } +tower-http = { version = "0", features = [ "compression-full", "cors", "propagate-header", "request-id", "trace" ] } tracing = "0" url = "2.5.4" [dev-dependencies] -reqwest = { version = "0", features = ["json"] } +reqwest = { version = "0", features = [ "json" ] } torrust-axum-health-check-api-server = { version = "3.0.0-develop", path = "../axum-health-check-api-server" } torrust-axum-http-tracker-server = { version = "3.0.0-develop", path = "../axum-http-tracker-server" } torrust-axum-rest-tracker-api-server = { version = "3.0.0-develop", path = "../axum-rest-tracker-api-server" } torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "../test-helpers" } torrust-udp-tracker-server = { version = "3.0.0-develop", path = "../udp-tracker-server" } -tracing-subscriber = { version = "0", features = ["json"] } +tracing-subscriber = { version = "0", features = [ "json" ] } diff --git a/packages/axum-http-tracker-server/Cargo.toml b/packages/axum-http-tracker-server/Cargo.toml index eb2c2cad3..88d073527 100644 --- a/packages/axum-http-tracker-server/Cargo.toml +++ b/packages/axum-http-tracker-server/Cargo.toml @@ -4,7 +4,7 @@ description = "The Torrust Bittorrent HTTP tracker." documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["axum", "bittorrent", "http", "server", "torrust", "tracker"] +keywords = [ "axum", "bittorrent", "http", "server", "torrust", "tracker" ] license.workspace = true name = "torrust-axum-http-tracker-server" publish.workspace = true @@ -15,19 +15,19 @@ version.workspace = true [dependencies] aquatic_udp_protocol = "0" -axum = { version = "0", features = ["macros"] } +axum = { version = "0", features = [ "macros" ] } axum-client-ip = "0" -axum-server = { version = "0", features = ["tls-rustls-no-provider"] } +axum-server = { version = "0", features = [ "tls-rustls-no-provider" ] } bittorrent-http-tracker-core = { version = "3.0.0-develop", path = "../http-tracker-core" } bittorrent-http-tracker-protocol = { version = "3.0.0-develop", path = "../http-protocol" } bittorrent-primitives = "0.1.0" bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } futures = "0" hyper = "1" -reqwest = { version = "0", features = ["json"] } -serde = { version = "1", features = ["derive"] } -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +reqwest = { version = "0", features = [ "json" ] } +serde = { version = "1", features = [ "derive" ] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-axum-server = { version = "3.0.0-develop", path = "../axum-server" } torrust-server-lib = { version = "3.0.0-develop", path = "../server-lib" } @@ -35,8 +35,8 @@ torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "../swarm-coordination-registry" } -tower = { version = "0", features = ["timeout"] } -tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } +tower = { version = "0", features = [ "timeout" ] } +tower-http = { version = "0", features = [ "compression-full", "cors", "propagate-header", "request-id", "trace" ] } tracing = "0" [dev-dependencies] @@ -49,5 +49,5 @@ serde_repr = "0" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-events = { version = "3.0.0-develop", path = "../events" } torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "../test-helpers" } -uuid = { version = "1", features = ["v4"] } +uuid = { version = "1", features = [ "v4" ] } zerocopy = "0.7" diff --git a/packages/axum-rest-tracker-api-server/Cargo.toml b/packages/axum-rest-tracker-api-server/Cargo.toml index 9493b8693..7353e66e8 100644 --- a/packages/axum-rest-tracker-api-server/Cargo.toml +++ b/packages/axum-rest-tracker-api-server/Cargo.toml @@ -4,7 +4,7 @@ description = "The Torrust Tracker API." documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["axum", "bittorrent", "http", "server", "torrust", "tracker"] +keywords = [ "axum", "bittorrent", "http", "server", "torrust", "tracker" ] license.workspace = true name = "torrust-axum-rest-tracker-api-server" publish.workspace = true @@ -15,22 +15,22 @@ version.workspace = true [dependencies] aquatic_udp_protocol = "0" -axum = { version = "0", features = ["macros"] } -axum-extra = { version = "0", features = ["query"] } -axum-server = { version = "0", features = ["tls-rustls-no-provider"] } +axum = { version = "0", features = [ "macros" ] } +axum-extra = { version = "0", features = [ "query" ] } +axum-server = { version = "0", features = [ "tls-rustls-no-provider" ] } bittorrent-http-tracker-core = { version = "3.0.0-develop", path = "../http-tracker-core" } bittorrent-primitives = "0.1.0" bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } bittorrent-udp-tracker-core = { version = "3.0.0-develop", path = "../udp-tracker-core" } -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } futures = "0" hyper = "1" -reqwest = { version = "0", features = ["json"] } -serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["preserve_order"] } -serde_with = { version = "3", features = ["json"] } +reqwest = { version = "0", features = [ "json" ] } +serde = { version = "1", features = [ "derive" ] } +serde_json = { version = "1", features = [ "preserve_order" ] } +serde_with = { version = "3", features = [ "json" ] } thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-axum-server = { version = "3.0.0-develop", path = "../axum-server" } torrust-rest-tracker-api-client = { version = "3.0.0-develop", path = "../rest-tracker-api-client" } torrust-rest-tracker-api-core = { version = "3.0.0-develop", path = "../rest-tracker-api-core" } @@ -41,8 +41,8 @@ torrust-tracker-metrics = { version = "3.0.0-develop", path = "../metrics" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "../swarm-coordination-registry" } torrust-udp-tracker-server = { version = "3.0.0-develop", path = "../udp-tracker-server" } -tower = { version = "0", features = ["timeout"] } -tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } +tower = { version = "0", features = [ "timeout" ] } +tower-http = { version = "0", features = [ "compression-full", "cors", "propagate-header", "request-id", "trace" ] } tracing = "0" url = "2" @@ -51,5 +51,5 @@ local-ip-address = "0" mockall = "0" torrust-rest-tracker-api-client = { version = "3.0.0-develop", path = "../rest-tracker-api-client" } torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "../test-helpers" } -url = { version = "2", features = ["serde"] } -uuid = { version = "1", features = ["v4"] } +url = { version = "2", features = [ "serde" ] } +uuid = { version = "1", features = [ "v4" ] } diff --git a/packages/axum-server/Cargo.toml b/packages/axum-server/Cargo.toml index a60bab885..45eddd3b0 100644 --- a/packages/axum-server/Cargo.toml +++ b/packages/axum-server/Cargo.toml @@ -4,7 +4,7 @@ description = "A wrapper for the Axum server for Torrust HTTP servers to add tim documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["axum", "server", "torrust", "wrapper"] +keywords = [ "axum", "server", "torrust", "wrapper" ] license.workspace = true name = "torrust-axum-server" publish.workspace = true @@ -14,19 +14,19 @@ rust-version.workspace = true version.workspace = true [dependencies] -axum-server = { version = "0", features = ["tls-rustls-no-provider"] } -camino = { version = "1", features = ["serde", "serde1"] } +axum-server = { version = "0", features = [ "tls-rustls-no-provider" ] } +camino = { version = "1", features = [ "serde", "serde1" ] } futures-util = "0" http-body = "1" hyper = "1" -hyper-util = { version = "0", features = ["http1", "http2", "tokio"] } +hyper-util = { version = "0", features = [ "http1", "http2", "tokio" ] } pin-project-lite = "0" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-server-lib = { version = "3.0.0-develop", path = "../server-lib" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-located-error = { version = "3.0.0-develop", path = "../located-error" } -tower = { version = "0", features = ["timeout"] } +tower = { version = "0", features = [ "timeout" ] } tracing = "0" [dev-dependencies] diff --git a/packages/clock/Cargo.toml b/packages/clock/Cargo.toml index 3bd00d2b0..c0cafff0a 100644 --- a/packages/clock/Cargo.toml +++ b/packages/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library to a clock for the torrust tracker." -keywords = ["clock", "library", "torrents"] +keywords = [ "clock", "library", "torrents" ] name = "torrust-tracker-clock" readme = "README.md" @@ -16,7 +16,7 @@ rust-version.workspace = true version.workspace = true [dependencies] -chrono = { version = "0", default-features = false, features = ["clock"] } +chrono = { version = "0", default-features = false, features = [ "clock" ] } lazy_static = "1" tracing = "0" diff --git a/packages/configuration/Cargo.toml b/packages/configuration/Cargo.toml index e213f7c0c..1155ba417 100644 --- a/packages/configuration/Cargo.toml +++ b/packages/configuration/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library to provide configuration to the Torrust Tracker." -keywords = ["config", "library", "settings"] +keywords = [ "config", "library", "settings" ] name = "torrust-tracker-configuration" readme = "README.md" @@ -15,18 +15,18 @@ rust-version.workspace = true version.workspace = true [dependencies] -camino = { version = "1", features = ["serde", "serde1"] } -derive_more = { version = "2", features = ["constructor", "display"] } -figment = { version = "0", features = ["env", "test", "toml"] } -serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["preserve_order"] } +camino = { version = "1", features = [ "serde", "serde1" ] } +derive_more = { version = "2", features = [ "constructor", "display" ] } +figment = { version = "0", features = [ "env", "test", "toml" ] } +serde = { version = "1", features = [ "derive" ] } +serde_json = { version = "1", features = [ "preserve_order" ] } serde_with = "3" thiserror = "2" toml = "0" torrust-tracker-located-error = { version = "3.0.0-develop", path = "../located-error" } tracing = "0" -tracing-subscriber = { version = "0", features = ["json"] } +tracing-subscriber = { version = "0", features = [ "json" ] } url = "2" [dev-dependencies] -uuid = { version = "1", features = ["v4"] } +uuid = { version = "1", features = [ "v4" ] } diff --git a/packages/events/Cargo.toml b/packages/events/Cargo.toml index 1d183cddb..165ecca68 100644 --- a/packages/events/Cargo.toml +++ b/packages/events/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with functionality to handle events in Torrust tracker packages." -keywords = ["events", "library", "rust", "torrust", "tracker"] +keywords = [ "events", "library", "rust", "torrust", "tracker" ] name = "torrust-tracker-events" readme = "README.md" @@ -16,7 +16,7 @@ version.workspace = true [dependencies] futures = "0" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync", "time"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync", "time" ] } [dev-dependencies] mockall = "0" diff --git a/packages/http-protocol/Cargo.toml b/packages/http-protocol/Cargo.toml index 7803fe78e..78a037b18 100644 --- a/packages/http-protocol/Cargo.toml +++ b/packages/http-protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with the primitive types and functions for the BitTorrent HTTP tracker protocol." -keywords = ["api", "library", "primitives"] +keywords = [ "api", "library", "primitives" ] name = "bittorrent-http-tracker-protocol" readme = "README.md" @@ -18,10 +18,10 @@ version.workspace = true aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } multimap = "0" percent-encoding = "2" -serde = { version = "1", features = ["derive"] } +serde = { version = "1", features = [ "derive" ] } serde_bencode = "0" thiserror = "2" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } diff --git a/packages/http-tracker-core/Cargo.toml b/packages/http-tracker-core/Cargo.toml index 04a6c96b6..c419052f9 100644 --- a/packages/http-tracker-core/Cargo.toml +++ b/packages/http-tracker-core/Cargo.toml @@ -4,7 +4,7 @@ description = "A library with the core functionality needed to implement a BitTo documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["api", "bittorrent", "core", "library", "tracker"] +keywords = [ "api", "bittorrent", "core", "library", "tracker" ] license.workspace = true name = "bittorrent-http-tracker-core" publish.workspace = true @@ -18,11 +18,11 @@ aquatic_udp_protocol = "0" bittorrent-http-tracker-protocol = { version = "3.0.0-develop", path = "../http-protocol" } bittorrent-primitives = "0.1.0" bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } -criterion = { version = "0.5.1", features = ["async_tokio"] } +criterion = { version = "0.5.1", features = [ "async_tokio" ] } futures = "0" serde = "1.0.219" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } diff --git a/packages/located-error/Cargo.toml b/packages/located-error/Cargo.toml index 29b0dfb2c..232a6113f 100644 --- a/packages/located-error/Cargo.toml +++ b/packages/located-error/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library to provide error decorator with the location and the source of the original error." -keywords = ["errors", "helper", "library"] +keywords = [ "errors", "helper", "library" ] name = "torrust-tracker-located-error" readme = "README.md" diff --git a/packages/metrics/Cargo.toml b/packages/metrics/Cargo.toml index 0597785f4..b6d327d70 100644 --- a/packages/metrics/Cargo.toml +++ b/packages/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with the primitive types shared by the Torrust tracker packages." -keywords = ["api", "library", "metrics"] +keywords = [ "api", "library", "metrics" ] name = "torrust-tracker-metrics" readme = "README.md" @@ -15,9 +15,9 @@ rust-version.workspace = true version.workspace = true [dependencies] -chrono = { version = "0", default-features = false, features = ["clock"] } -derive_more = { version = "2", features = ["constructor"] } -serde = { version = "1", features = ["derive"] } +chrono = { version = "0", default-features = false, features = [ "clock" ] } +derive_more = { version = "2", features = [ "constructor" ] } +serde = { version = "1", features = [ "derive" ] } serde_json = "1.0.140" thiserror = "2" torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } diff --git a/packages/primitives/Cargo.toml b/packages/primitives/Cargo.toml index 21fab09bf..c9ce64177 100644 --- a/packages/primitives/Cargo.toml +++ b/packages/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with the primitive types shared by the Torrust tracker packages." -keywords = ["api", "library", "primitives"] +keywords = [ "api", "library", "primitives" ] name = "torrust-tracker-primitives" readme = "README.md" @@ -18,8 +18,8 @@ version.workspace = true aquatic_udp_protocol = "0" binascii = "0" bittorrent-primitives = "0.1.0" -derive_more = { version = "2", features = ["constructor"] } -serde = { version = "1", features = ["derive"] } +derive_more = { version = "2", features = [ "constructor" ] } +serde = { version = "1", features = [ "derive" ] } tdyne-peer-id = "1" tdyne-peer-id-registry = "0" thiserror = "2" diff --git a/packages/rest-tracker-api-client/Cargo.toml b/packages/rest-tracker-api-client/Cargo.toml index c01b9c05a..47307df9a 100644 --- a/packages/rest-tracker-api-client/Cargo.toml +++ b/packages/rest-tracker-api-client/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library to interact with the Torrust Tracker REST API." -keywords = ["bittorrent", "client", "tracker"] +keywords = [ "bittorrent", "client", "tracker" ] license = "LGPL-3.0" name = "torrust-rest-tracker-api-client" readme = "README.md" @@ -16,8 +16,8 @@ version.workspace = true [dependencies] hyper = "1" -reqwest = { version = "0", features = ["json", "query"] } -serde = { version = "1", features = ["derive"] } +reqwest = { version = "0", features = [ "json", "query" ] } +serde = { version = "1", features = [ "derive" ] } thiserror = "2" -url = { version = "2", features = ["serde"] } -uuid = { version = "1", features = ["v4"] } +url = { version = "2", features = [ "serde" ] } +uuid = { version = "1", features = [ "v4" ] } diff --git a/packages/rest-tracker-api-core/Cargo.toml b/packages/rest-tracker-api-core/Cargo.toml index be6d493d7..0808c2dd6 100644 --- a/packages/rest-tracker-api-core/Cargo.toml +++ b/packages/rest-tracker-api-core/Cargo.toml @@ -4,7 +4,7 @@ description = "A library with the core functionality needed to implement a BitTo documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["api", "bittorrent", "core", "library", "tracker"] +keywords = [ "api", "bittorrent", "core", "library", "tracker" ] license.workspace = true name = "torrust-rest-tracker-api-core" publish.workspace = true @@ -17,7 +17,7 @@ version.workspace = true bittorrent-http-tracker-core = { version = "3.0.0-develop", path = "../http-tracker-core" } bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } bittorrent-udp-tracker-core = { version = "3.0.0-develop", path = "../udp-tracker-core" } -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-metrics = { version = "3.0.0-develop", path = "../metrics" } diff --git a/packages/server-lib/Cargo.toml b/packages/server-lib/Cargo.toml index 1d30e7fb5..fbd7a7a7f 100644 --- a/packages/server-lib/Cargo.toml +++ b/packages/server-lib/Cargo.toml @@ -4,7 +4,7 @@ description = "Common functionality used in all Torrust HTTP servers." documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["lib", "server", "torrust"] +keywords = [ "lib", "server", "torrust" ] license.workspace = true name = "torrust-server-lib" publish.workspace = true @@ -14,10 +14,10 @@ rust-version.workspace = true version.workspace = true [dependencies] -derive_more = { version = "2", features = ["as_ref", "constructor", "display", "from"] } -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "display", "from" ] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } -tower-http = { version = "0", features = ["compression-full", "cors", "propagate-header", "request-id", "trace"] } +tower-http = { version = "0", features = [ "compression-full", "cors", "propagate-header", "request-id", "trace" ] } tracing = "0" [dev-dependencies] diff --git a/packages/swarm-coordination-registry/Cargo.toml b/packages/swarm-coordination-registry/Cargo.toml index 45359ad81..f9513d3c4 100644 --- a/packages/swarm-coordination-registry/Cargo.toml +++ b/packages/swarm-coordination-registry/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library that provides a repository of torrents files and their peers." -keywords = ["library", "repository", "torrents"] +keywords = [ "library", "repository", "torrents" ] name = "torrust-tracker-swarm-coordination-registry" readme = "README.md" @@ -18,12 +18,12 @@ version.workspace = true [dependencies] aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" -chrono = { version = "0", default-features = false, features = ["clock"] } +chrono = { version = "0", default-features = false, features = [ "clock" ] } crossbeam-skiplist = "0" futures = "0" -serde = { version = "1.0.219", features = ["derive"] } +serde = { version = "1.0.219", features = [ "derive" ] } thiserror = "2.0.12" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } @@ -33,8 +33,8 @@ torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" tracing = "0" [dev-dependencies] -async-std = { version = "1", features = ["attributes", "tokio1"] } -criterion = { version = "0", features = ["async_tokio"] } +async-std = { version = "1", features = [ "attributes", "tokio1" ] } +criterion = { version = "0", features = [ "async_tokio" ] } mockall = "0" rand = "0" rstest = "0" diff --git a/packages/test-helpers/Cargo.toml b/packages/test-helpers/Cargo.toml index 3495c314a..fb240730d 100644 --- a/packages/test-helpers/Cargo.toml +++ b/packages/test-helpers/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library providing helpers for testing the Torrust tracker." -keywords = ["helper", "library", "testing"] +keywords = [ "helper", "library", "testing" ] name = "torrust-tracker-test-helpers" readme = "README.md" @@ -18,4 +18,4 @@ version.workspace = true rand = "0" torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } tracing = "0" -tracing-subscriber = { version = "0", features = ["json"] } +tracing-subscriber = { version = "0", features = [ "json" ] } diff --git a/packages/torrent-repository-benchmarking/Cargo.toml b/packages/torrent-repository-benchmarking/Cargo.toml index 1a93c513c..653ad8102 100644 --- a/packages/torrent-repository-benchmarking/Cargo.toml +++ b/packages/torrent-repository-benchmarking/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library to runt benchmarking for different implementations of a repository of torrents files and their peers." -keywords = ["library", "repository", "torrents"] +keywords = [ "library", "repository", "torrents" ] name = "torrust-tracker-torrent-repository-benchmarking" readme = "README.md" @@ -22,15 +22,15 @@ crossbeam-skiplist = "0" dashmap = "6" futures = "0" parking_lot = "0" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } zerocopy = "0.7" [dev-dependencies] -async-std = { version = "1", features = ["attributes", "tokio1"] } -criterion = { version = "0", features = ["async_tokio"] } +async-std = { version = "1", features = [ "attributes", "tokio1" ] } +criterion = { version = "0", features = [ "async_tokio" ] } rstest = "0" [[bench]] diff --git a/packages/tracker-client/Cargo.toml b/packages/tracker-client/Cargo.toml index ef5cccaa2..0cd419471 100644 --- a/packages/tracker-client/Cargo.toml +++ b/packages/tracker-client/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with the generic tracker clients." -keywords = ["bittorrent", "client", "tracker"] +keywords = [ "bittorrent", "client", "tracker" ] license = "LGPL-3.0" name = "bittorrent-tracker-client" readme = "README.md" @@ -17,16 +17,16 @@ version.workspace = true [dependencies] aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } hyper = "1" percent-encoding = "2" -reqwest = { version = "0", features = ["json"] } -serde = { version = "1", features = ["derive"] } +reqwest = { version = "0", features = [ "json" ] } +serde = { version = "1", features = [ "derive" ] } serde_bencode = "0" serde_bytes = "0" serde_repr = "0" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } torrust-tracker-located-error = { version = "3.0.0-develop", path = "../located-error" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } @@ -34,4 +34,4 @@ tracing = "0" zerocopy = "0.7" [package.metadata.cargo-machete] -ignored = ["serde_bytes"] +ignored = [ "serde_bytes" ] diff --git a/packages/tracker-core/Cargo.toml b/packages/tracker-core/Cargo.toml index dfc83e58e..fb864cde7 100644 --- a/packages/tracker-core/Cargo.toml +++ b/packages/tracker-core/Cargo.toml @@ -4,7 +4,7 @@ description = "A library with the core functionality needed to implement a BitTo documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["api", "bittorrent", "core", "library", "tracker"] +keywords = [ "api", "bittorrent", "core", "library", "tracker" ] license.workspace = true name = "bittorrent-tracker-core" publish.workspace = true @@ -16,17 +16,17 @@ version.workspace = true [dependencies] aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" -chrono = { version = "0", default-features = false, features = ["clock"] } -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +chrono = { version = "0", default-features = false, features = [ "clock" ] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } mockall = "0" r2d2 = "0" r2d2_mysql = "25" -r2d2_sqlite = { version = "0", features = ["bundled"] } +r2d2_sqlite = { version = "0", features = [ "bundled" ] } rand = "0" -serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["preserve_order"] } +serde = { version = "1", features = [ "derive" ] } +serde_json = { version = "1", features = [ "preserve_order" ] } thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } diff --git a/packages/udp-protocol/Cargo.toml b/packages/udp-protocol/Cargo.toml index 31fd52af8..3bcde9a95 100644 --- a/packages/udp-protocol/Cargo.toml +++ b/packages/udp-protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] description = "A library with the primitive types and functions for the BitTorrent UDP tracker protocol." -keywords = ["bittorrent", "library", "primitives", "udp"] +keywords = [ "bittorrent", "library", "primitives", "udp" ] name = "bittorrent-udp-tracker-protocol" readme = "README.md" diff --git a/packages/udp-tracker-core/Cargo.toml b/packages/udp-tracker-core/Cargo.toml index aa12f898f..828b3aff2 100644 --- a/packages/udp-tracker-core/Cargo.toml +++ b/packages/udp-tracker-core/Cargo.toml @@ -4,7 +4,7 @@ description = "A library with the core functionality needed to implement a BitTo documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["api", "bittorrent", "core", "library", "tracker"] +keywords = [ "api", "bittorrent", "core", "library", "tracker" ] license.workspace = true name = "bittorrent-udp-tracker-core" publish.workspace = true @@ -21,14 +21,14 @@ bittorrent-udp-tracker-protocol = { version = "3.0.0-develop", path = "../udp-pr bloom = "0.3.2" blowfish = "0" cipher = "0.4" -criterion = { version = "0.5.1", features = ["async_tokio"] } +criterion = { version = "0.5.1", features = [ "async_tokio" ] } futures = "0" generic-array = "0" lazy_static = "1" rand = "0" serde = "1.0.219" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync", "time"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync", "time" ] } tokio-util = "0.7.15" torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } torrust-tracker-configuration = { version = "3.0.0-develop", path = "../configuration" } diff --git a/packages/udp-tracker-server/Cargo.toml b/packages/udp-tracker-server/Cargo.toml index 160fe58f9..dc66572d8 100644 --- a/packages/udp-tracker-server/Cargo.toml +++ b/packages/udp-tracker-server/Cargo.toml @@ -4,7 +4,7 @@ description = "The Torrust Bittorrent UDP tracker." documentation.workspace = true edition.workspace = true homepage.workspace = true -keywords = ["axum", "bittorrent", "server", "torrust", "tracker", "udp"] +keywords = [ "axum", "bittorrent", "server", "torrust", "tracker", "udp" ] license.workspace = true name = "torrust-udp-tracker-server" publish.workspace = true @@ -19,13 +19,13 @@ bittorrent-primitives = "0.1.0" bittorrent-tracker-client = { version = "3.0.0-develop", path = "../tracker-client" } bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" } bittorrent-udp-tracker-core = { version = "3.0.0-develop", path = "../udp-tracker-core" } -derive_more = { version = "2", features = ["as_ref", "constructor", "from"] } +derive_more = { version = "2", features = [ "as_ref", "constructor", "from" ] } futures = "0" futures-util = "0" ringbuf = "0" serde = "1.0.219" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] } +tokio = { version = "1", features = [ "macros", "net", "rt-multi-thread", "signal", "sync" ] } tokio-util = "0.7.15" torrust-server-lib = { version = "3.0.0-develop", path = "../server-lib" } torrust-tracker-clock = { version = "3.0.0-develop", path = "../clock" } @@ -35,8 +35,8 @@ torrust-tracker-metrics = { version = "3.0.0-develop", path = "../metrics" } torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives" } torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "../swarm-coordination-registry" } tracing = "0" -url = { version = "2", features = ["serde"] } -uuid = { version = "1", features = ["v4"] } +url = { version = "2", features = [ "serde" ] } +uuid = { version = "1", features = [ "v4" ] } zerocopy = "0.7" [dev-dependencies] From 1d3ba500e9404c971703f24a3e2132dc62486304 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 8 Apr 2026 16:59:16 +0100 Subject: [PATCH 47/79] ci(lint): switch testing workflow to internal linting tool --- .github/workflows/testing.yaml | 39 ++++++++++++---------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index c9328d890..83a290663 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -33,9 +33,10 @@ jobs: run: cargo fmt --check check: - name: Static Analysis + name: Linting runs-on: ubuntu-latest needs: format + timeout-minutes: 15 strategy: matrix: @@ -51,39 +52,25 @@ jobs: uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.toolchain }} - components: clippy + components: clippy, rustfmt + + - id: node + name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: "20" - id: cache name: Enable Workflow Cache uses: Swatinem/rust-cache@v2 - id: tools - name: Install Tools - uses: taiki-e/install-action@v2 - with: - tool: cargo-machete - - - id: check - name: Run Build Checks - run: cargo check --tests --benches --examples --workspace --all-targets --all-features + name: Install Internal Linter + run: cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter - id: lint - name: Run Lint Checks - run: cargo clippy --tests --benches --examples --workspace --all-targets --all-features - - - id: docs - name: Lint Documentation - env: - RUSTDOCFLAGS: "-D warnings" - run: cargo doc --no-deps --bins --examples --workspace --all-features - - - id: clean - name: Clean Build Directory - run: cargo clean - - - id: deps - name: Check Unused Dependencies - run: cargo machete + name: Run All Linters + run: linter all build: name: Build on ${{ matrix.os }} (${{ matrix.toolchain }}) From b90e091a51b82daeeab9f85c196957343f659919 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 15 Apr 2026 19:04:42 +0100 Subject: [PATCH 48/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 34 packages to latest compatible versions Updating axum v0.8.8 -> v0.8.9 Updating axum-extra v0.12.5 -> v0.12.6 Updating axum-macros v0.5.0 -> v0.5.1 Updating bitflags v2.11.0 -> v2.11.1 Updating blowfish v0.9.1 -> v0.10.0 Updating cc v1.2.59 -> v1.2.60 Adding cipher v0.5.1 Adding crypto-common v0.2.1 Adding hashbrown v0.17.0 Adding hybrid-array v0.4.10 Updating hyper-rustls v0.27.7 -> v0.27.9 Updating indexmap v2.13.1 -> v2.14.0 Adding inout v0.2.2 Updating js-sys v0.3.94 -> v0.3.95 Updating libc v0.2.184 -> v0.2.185 Updating libredox v0.1.15 -> v0.1.16 Updating openssl v0.10.76 -> v0.10.77 Updating openssl-sys v0.9.112 -> v0.9.113 Updating pkg-config v0.3.32 -> v0.3.33 Removing rand v0.9.2 Removing rand v0.10.0 Adding rand v0.9.4 Adding rand v0.10.1 Updating rand_core v0.10.0 -> v0.10.1 Updating rayon v1.11.0 -> v1.12.0 Updating redox_syscall v0.7.3 -> v0.7.4 Updating rustls v0.23.37 -> v0.23.38 Updating rustls-webpki v0.103.10 -> v0.103.12 Updating tokio v1.51.0 -> v1.52.0 Updating toml_edit v0.25.10+spec-1.1.0 -> v0.25.11+spec-1.1.0 Updating wasm-bindgen v0.2.117 -> v0.2.118 Updating wasm-bindgen-futures v0.4.67 -> v0.4.68 Updating wasm-bindgen-macro v0.2.117 -> v0.2.118 Updating wasm-bindgen-macro-support v0.2.117 -> v0.2.118 Updating wasm-bindgen-shared v0.2.117 -> v0.2.118 Updating web-sys v0.3.94 -> v0.3.95 note: pass `--verbose` to see 9 unchanged dependencies behind latest ``` --- Cargo.lock | 232 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e0911944..27a9a8f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,9 +419,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "axum-macros", @@ -483,9 +483,9 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef252edff26ddba56bbcdf2ee3307b8129acb86f5749b68990c168a6fcc9c76" +checksum = "be44683b41ccb9ab2d23a5230015c9c3c55be97a25e4428366de8873103f7970" dependencies = [ "axum", "axum-core", @@ -508,9 +508,9 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", @@ -620,9 +620,9 @@ checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bittorrent-http-tracker-core" @@ -721,7 +721,7 @@ dependencies = [ "r2d2", "r2d2_mysql", "r2d2_sqlite", - "rand 0.10.0", + "rand 0.10.1", "serde", "serde_json", "testcontainers", @@ -751,13 +751,13 @@ dependencies = [ "bittorrent-udp-tracker-protocol", "bloom", "blowfish", - "cipher", + "cipher 0.4.4", "criterion 0.5.1", "futures", "generic-array", "lazy_static", "mockall", - "rand 0.10.0", + "rand 0.10.1", "serde", "thiserror 2.0.18", "tokio", @@ -827,12 +827,12 @@ dependencies = [ [[package]] name = "blowfish" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +checksum = "62ce3946557b35e71d1bbe07ec385073ce9eda05043f95de134eb578fcf1a298" dependencies = [ "byteorder", - "cipher", + "cipher 0.5.1", ] [[package]] @@ -861,7 +861,7 @@ dependencies = [ "log", "num", "pin-project-lite", - "rand 0.9.2", + "rand 0.9.4", "rustls", "rustls-native-certs", "rustls-pki-types", @@ -1041,9 +1041,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.59" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -1086,7 +1086,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -1134,8 +1134,18 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", - "inout", + "crypto-common 0.1.7", + "inout 0.1.4", +] + +[[package]] +name = "cipher" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" +dependencies = [ + "crypto-common 0.2.1", + "inout 0.2.2", ] [[package]] @@ -1474,6 +1484,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + [[package]] name = "darling" version = "0.20.11" @@ -1645,7 +1664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "crypto-common", + "crypto-common 0.1.7", ] [[package]] @@ -1801,7 +1820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb330bbd4cb7a5b9f559427f06f98a4f853a137c8298f3bd3f8ca57663e21986" dependencies = [ "portable-atomic", - "rand 0.9.2", + "rand 0.9.4", "web-time", ] @@ -2151,7 +2170,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -2204,7 +2223,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -2257,6 +2276,12 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "hashlink" version = "0.11.0" @@ -2344,6 +2369,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.9.0" @@ -2383,15 +2417,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -2602,12 +2635,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -2627,6 +2660,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "hybrid-array", +] + [[package]] name = "io-enum" version = "1.2.1" @@ -2764,9 +2806,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "cfg-if", "futures-util", @@ -2797,9 +2839,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libloading" @@ -2819,14 +2861,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -3287,9 +3329,9 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "bfe4646e360ec77dff7dde40ed3d6c5fee52d156ef4a62f53973d38294dad87f" dependencies = [ "bitflags", "cfg-if", @@ -3319,9 +3361,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "ad2f2c0eba47118757e4c6d2bff2838f3e0523380021356e7875e858372ce644" dependencies = [ "cc", "libc", @@ -3521,9 +3563,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -3664,7 +3706,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.10+spec-1.1.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -3771,7 +3813,7 @@ checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b" dependencies = [ "env_logger", "log", - "rand 0.10.0", + "rand 0.10.1", ] [[package]] @@ -3804,7 +3846,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -3902,9 +3944,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -3912,13 +3954,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -3961,15 +4003,15 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -3996,9 +4038,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags", ] @@ -4299,9 +4341,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" dependencies = [ "aws-lc-rs", "log", @@ -4364,9 +4406,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" dependencies = [ "aws-lc-rs", "ring", @@ -4541,7 +4583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "ryu", "serde_core", @@ -4553,7 +4595,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "memchr", "serde", @@ -4623,7 +4665,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.1", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -5113,9 +5155,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.51.0" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ "bytes", "libc", @@ -5190,7 +5232,7 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde_core", "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", @@ -5232,7 +5274,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -5242,11 +5284,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.10+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.1", @@ -5358,7 +5400,7 @@ dependencies = [ "hyper", "local-ip-address", "percent-encoding", - "rand 0.10.0", + "rand 0.10.1", "reqwest", "serde", "serde_bencode", @@ -5499,7 +5541,7 @@ dependencies = [ "clap", "local-ip-address", "mockall", - "rand 0.10.0", + "rand 0.10.1", "regex", "reqwest", "serde", @@ -5649,7 +5691,7 @@ dependencies = [ "crossbeam-skiplist", "futures", "mockall", - "rand 0.10.0", + "rand 0.10.1", "rstest 0.26.1", "serde", "thiserror 2.0.18", @@ -5668,7 +5710,7 @@ dependencies = [ name = "torrust-tracker-test-helpers" version = "3.0.0-develop" dependencies = [ - "rand 0.10.0", + "rand 0.10.1", "torrust-tracker-configuration", "tracing", "tracing-subscriber", @@ -5708,7 +5750,7 @@ dependencies = [ "futures-util", "local-ip-address", "mockall", - "rand 0.10.0", + "rand 0.10.1", "ringbuf", "serde", "thiserror 2.0.18", @@ -5736,7 +5778,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.13.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper", @@ -5994,7 +6036,7 @@ checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ "getrandom 0.4.2", "js-sys", - "rand 0.10.0", + "rand 0.10.1", "wasm-bindgen", ] @@ -6067,9 +6109,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -6081,9 +6123,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ "js-sys", "wasm-bindgen", @@ -6091,9 +6133,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6101,9 +6143,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -6114,9 +6156,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] @@ -6138,7 +6180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.1", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -6151,15 +6193,15 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", - "indexmap 2.13.1", + "indexmap 2.14.0", "semver", ] [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -6553,7 +6595,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", - "indexmap 2.13.1", + "indexmap 2.14.0", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -6584,7 +6626,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -6603,7 +6645,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "semver", "serde", From 7b5f4b45363fdad369effbc64727ee69a3014f7d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 15 Apr 2026 21:13:29 +0100 Subject: [PATCH 49/79] fix(udp-tracker-core): align cipher with blowfish update --- Cargo.lock | 26 +++---------------- packages/udp-tracker-core/Cargo.toml | 3 +-- .../udp-tracker-core/src/connection_cookie.rs | 9 +++---- .../src/crypto/ephemeral_instance_keys.rs | 5 ++-- packages/udp-tracker-core/src/crypto/keys.rs | 8 +++--- 5 files changed, 14 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27a9a8f1a..81c8c62b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -751,10 +751,9 @@ dependencies = [ "bittorrent-udp-tracker-protocol", "bloom", "blowfish", - "cipher 0.4.4", + "cipher", "criterion 0.5.1", "futures", - "generic-array", "lazy_static", "mockall", "rand 0.10.1", @@ -832,7 +831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62ce3946557b35e71d1bbe07ec385073ce9eda05043f95de134eb578fcf1a298" dependencies = [ "byteorder", - "cipher 0.5.1", + "cipher", ] [[package]] @@ -1128,16 +1127,6 @@ dependencies = [ "half", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout 0.1.4", -] - [[package]] name = "cipher" version = "0.5.1" @@ -1145,7 +1134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" dependencies = [ "crypto-common 0.2.1", - "inout 0.2.2", + "inout", ] [[package]] @@ -2651,15 +2640,6 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - [[package]] name = "inout" version = "0.2.2" diff --git a/packages/udp-tracker-core/Cargo.toml b/packages/udp-tracker-core/Cargo.toml index 828b3aff2..45a74f93c 100644 --- a/packages/udp-tracker-core/Cargo.toml +++ b/packages/udp-tracker-core/Cargo.toml @@ -20,10 +20,9 @@ bittorrent-tracker-core = { version = "3.0.0-develop", path = "../tracker-core" bittorrent-udp-tracker-protocol = { version = "3.0.0-develop", path = "../udp-protocol" } bloom = "0.3.2" blowfish = "0" -cipher = "0.4" +cipher = "0.5" criterion = { version = "0.5.1", features = [ "async_tokio" ] } futures = "0" -generic-array = "0" lazy_static = "1" rand = "0" serde = "1.0.219" diff --git a/packages/udp-tracker-core/src/connection_cookie.rs b/packages/udp-tracker-core/src/connection_cookie.rs index ce255705f..2d8e941cd 100644 --- a/packages/udp-tracker-core/src/connection_cookie.rs +++ b/packages/udp-tracker-core/src/connection_cookie.rs @@ -84,7 +84,6 @@ use tracing::instrument; use zerocopy::AsBytes; use crate::crypto::keys::CipherArrayBlowfish; - /// Error returned when there was an error with the connection cookie. #[derive(Error, Debug, Clone, PartialEq)] pub enum ConnectionCookieError { @@ -140,8 +139,8 @@ use std::ops::Range; pub fn check(cookie: &Cookie, fingerprint: u64, valid_range: Range) -> Result { assert!(valid_range.start <= valid_range.end, "range start is larger than range end"); - let cookie_bytes = CipherArrayBlowfish::from_slice(cookie.0.as_bytes()); - let cookie_bytes = decode(*cookie_bytes); + let cookie_bytes = CipherArrayBlowfish::try_from(cookie.0.as_bytes()).expect("it should be the same size"); + let cookie_bytes = decode(cookie_bytes); let issue_time = disassemble(fingerprint, cookie_bytes); @@ -176,7 +175,7 @@ pub fn gen_remote_fingerprint(remote_addr: &SocketAddr) -> u64 { } mod cookie_builder { - use cipher::{BlockDecrypt, BlockEncrypt}; + use cipher::{BlockCipherDecrypt, BlockCipherEncrypt}; use tracing::instrument; use zerocopy::{byteorder, AsBytes as _, NativeEndian}; @@ -196,7 +195,7 @@ mod cookie_builder { let cookie: byteorder::I64 = *zerocopy::FromBytes::ref_from(&cookie.to_ne_bytes()).expect("it should be aligned"); - *CipherArrayBlowfish::from_slice(cookie.as_bytes()) + CipherArrayBlowfish::try_from(cookie.as_bytes()).expect("it should be the same size") } #[instrument()] diff --git a/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs b/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs index de40e4b1d..357bdeca5 100644 --- a/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs +++ b/packages/udp-tracker-core/src/crypto/ephemeral_instance_keys.rs @@ -4,14 +4,13 @@ //! application starts and are not persisted anywhere. use blowfish::BlowfishLE; -use cipher::{BlockSizeUser, KeyInit}; -use generic_array::GenericArray; +use cipher::{Block, KeyInit}; use rand::rngs::ThreadRng; use rand::RngExt; pub type Seed = [u8; 32]; pub type CipherBlowfish = BlowfishLE; -pub type CipherArrayBlowfish = GenericArray::BlockSize>; +pub type CipherArrayBlowfish = Block; lazy_static! { /// The random static seed. diff --git a/packages/udp-tracker-core/src/crypto/keys.rs b/packages/udp-tracker-core/src/crypto/keys.rs index bb813b9dc..2faa745c3 100644 --- a/packages/udp-tracker-core/src/crypto/keys.rs +++ b/packages/udp-tracker-core/src/crypto/keys.rs @@ -5,7 +5,7 @@ //! //! It also provides the logic for the cipher for encryption and decryption. -use cipher::{BlockDecrypt, BlockEncrypt}; +use cipher::{BlockCipherDecrypt, BlockCipherEncrypt}; use self::detail_cipher::CURRENT_CIPHER; use self::detail_seed::CURRENT_SEED; @@ -15,7 +15,7 @@ use crate::crypto::ephemeral_instance_keys::{CipherBlowfish, Seed, RANDOM_CIPHER /// This trait is for structures that can keep and provide a seed. pub trait Keeper { type Seed: Sized + Default + AsMut<[u8]>; - type Cipher: BlockEncrypt + BlockDecrypt; + type Cipher: BlockCipherEncrypt + BlockCipherDecrypt; /// It returns a reference to the seed that is keeping. fn get_seed() -> &'static Self::Seed; @@ -137,14 +137,14 @@ mod detail_cipher { #[cfg(test)] mod tests { - use cipher::BlockEncrypt; + use cipher::BlockCipherEncrypt; use crate::crypto::ephemeral_instance_keys::{CipherArrayBlowfish, ZEROED_TEST_CIPHER_BLOWFISH}; use crate::crypto::keys::detail_cipher::CURRENT_CIPHER; #[test] fn it_should_default_to_zeroed_seed_when_testing() { - let mut data: cipher::generic_array::GenericArray = CipherArrayBlowfish::from([0u8; 8]); + let mut data = CipherArrayBlowfish::from([0u8; 8]); let mut data_2 = CipherArrayBlowfish::from([0u8; 8]); CURRENT_CIPHER.encrypt_block(&mut data); From a55c2aefe699c9ecbbd3c4a85d653eef145e6290 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 16 Apr 2026 17:28:03 +0100 Subject: [PATCH 50/79] chore(deps): update dependencies ``` cargo update Updating crates.io index Locking 9 packages to latest compatible versions Updating aws-lc-rs v1.16.2 -> v1.16.3 Updating aws-lc-sys v0.39.1 -> v0.40.0 Updating clap v4.6.0 -> v4.6.1 Updating clap_derive v4.6.0 -> v4.6.1 Updating ferroid v0.8.9 -> v2.0.0 Updating portable-atomic-util v0.2.6 -> v0.2.7 Updating testcontainers v0.27.2 -> v0.27.3 Updating uuid v1.23.0 -> v1.23.1 Updating webpki-root-certs v1.0.6 -> v1.0.7 note: pass `--verbose` to see 8 unchanged dependencies behind latest ``` --- Cargo.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81c8c62b0..03138f718 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -397,9 +397,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-sys", "zeroize", @@ -407,9 +407,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "cc", "cmake", @@ -1150,9 +1150,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -1172,9 +1172,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -1804,12 +1804,12 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "ferroid" -version = "0.8.9" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb330bbd4cb7a5b9f559427f06f98a4f853a137c8298f3bd3f8ca57663e21986" +checksum = "ee93edf3c501f0035bbeffeccfed0b79e14c311f12195ec0e661e114a0f60da4" dependencies = [ "portable-atomic", - "rand 0.9.4", + "rand 0.10.1", "web-time", ] @@ -3603,9 +3603,9 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] @@ -4979,9 +4979,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "testcontainers" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd36b06a2a6c0c3c81a83be1ab05fe86460d054d4d51bf513bc56b3e15bdc22" +checksum = "bfd5785b5483672915ed5fe3cddf9f546802779fc1eceff0a6fb7321fac81c1e" dependencies = [ "astral-tokio-tar", "async-trait", @@ -6010,9 +6010,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -6199,9 +6199,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] From e47a5e9f24dc1ecf39bd08882518e60972e4a45c Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 16 Apr 2026 17:33:55 +0100 Subject: [PATCH 51/79] chore(ci): upgrade codecov/codecov-action from v5 to v6 --- .github/workflows/coverage.yaml | 2 +- .github/workflows/upload_coverage_pr.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 4c49217c2..ada96f77f 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -49,7 +49,7 @@ jobs: - id: upload name: Upload Coverage Report - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: verbose: true token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/upload_coverage_pr.yaml b/.github/workflows/upload_coverage_pr.yaml index 55de02c62..4a6c757a5 100644 --- a/.github/workflows/upload_coverage_pr.yaml +++ b/.github/workflows/upload_coverage_pr.yaml @@ -102,7 +102,7 @@ jobs: path: repo_root - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: verbose: true token: ${{ secrets.CODECOV_TOKEN }} From 92929ba9f77022c94af5020be7135cc52bd335a4 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 16 Apr 2026 18:02:04 +0100 Subject: [PATCH 52/79] docs(#1595): Add build-essential to Prerequisites The build-essential package is required to provide the C compiler (cc) needed for compilation. This was missing from the prerequisites documentation. Closes #1595 --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b26960899..791c0d928 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,12 @@ //! //! The tracker has some system dependencies: //! +//! First, you need to install the build tools: +//! +//! ```text +//! sudo apt-get install build-essential +//! ``` +//! //! Since we are using the `openssl` crate with the [vendored feature](https://docs.rs/openssl/latest/openssl/#vendored), //! enabled, you will need to install the following dependencies: //! From bcbef65801ebc3798a6d803b57385537fc677d7e Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 16 Apr 2026 18:24:58 +0100 Subject: [PATCH 53/79] docs(configuration): document MySQL DSN password URL-encoding --- docs/containers.md | 6 +++++- packages/configuration/src/v2_0_0/database.rs | 4 +++- share/default/config/tracker.container.mysql.toml | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/containers.md b/docs/containers.md index cddd2ba98..a7754d8aa 100644 --- a/docs/containers.md +++ b/docs/containers.md @@ -248,6 +248,10 @@ driver = "mysql" path = "mysql://db_user:db_user_secret_password@mysql:3306/torrust_tracker" ``` +Important: if the MySQL password contains reserved URL characters (for example `+`, `/`, `@`, or `:`), it must be percent-encoded in the DSN password component. For example, if the raw password is `a+b/c`, use `a%2Bb%2Fc` in the DSN. + +When generating secrets automatically, prefer URL-safe passwords (`A-Z`, `a-z`, `0-9`, `-`, `_`) to avoid DSN parsing issues. + ### Build and Run: ```sh @@ -292,7 +296,7 @@ These are some useful commands for MySQL. Open a shell in the MySQL container using docker or docker-compose. ```s -docker exec -it torrust-mysql-1 /bin/bash +docker exec -it torrust-mysql-1 /bin/bash docker compose exec mysql /bin/bash ``` diff --git a/packages/configuration/src/v2_0_0/database.rs b/packages/configuration/src/v2_0_0/database.rs index c2b24d809..457b3c925 100644 --- a/packages/configuration/src/v2_0_0/database.rs +++ b/packages/configuration/src/v2_0_0/database.rs @@ -12,8 +12,10 @@ pub struct Database { /// Database connection string. The format depends on the database driver. /// For `sqlite3`, the format is `path/to/database.db`, for example: /// `./storage/tracker/lib/database/sqlite3.db`. - /// For `Mysql`, the format is `mysql://db_user:db_user_password:port/db_name`, for + /// For `mysql`, the format is `mysql://db_user:db_user_password@host:port/db_name`, for /// example: `mysql://root:password@localhost:3306/torrust`. + /// If the password contains reserved URL characters (for example `+` or `/`), + /// percent-encode it in the URL. #[serde(default = "Database::default_path")] pub path: String, } diff --git a/share/default/config/tracker.container.mysql.toml b/share/default/config/tracker.container.mysql.toml index 865ea224e..33fcf713a 100644 --- a/share/default/config/tracker.container.mysql.toml +++ b/share/default/config/tracker.container.mysql.toml @@ -12,6 +12,9 @@ private = false [core.database] driver = "mysql" +# If the MySQL password includes reserved URL characters (for example + or /), +# percent-encode it in the DSN password component. +# Example: password a+b/c -> a%2Bb%2Fc path = "mysql://db_user:db_user_secret_password@mysql:3306/torrust_tracker" # Uncomment to enable services From e7a3a8aef0c006a7226437d2d285dc0fd95a8883 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 15:55:02 +0100 Subject: [PATCH 54/79] chore: update dependencies ``` cargo update Updating crates.io index Locking 8 packages to latest compatible versions Updating openssl v0.10.77 -> v0.10.78 Updating openssl-sys v0.9.113 -> v0.9.114 Updating rand v0.8.5 -> v0.8.6 Updating sqlite-wasm-rs v0.5.2 -> v0.5.3 Updating tokio v1.52.0 -> v1.52.1 Updating typenum v1.19.0 -> v1.20.0 Updating wasip2 v1.0.2+wasi-0.2.9 -> v1.0.3+wasi-0.2.9 Adding wit-bindgen v0.57.1 note: pass `--verbose` to see 8 unchanged dependencies behind latest ``` --- Cargo.lock | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03138f718..bb8a972b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3105,7 +3105,7 @@ dependencies = [ "mysql-common-derive", "num-bigint", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "regex", "rust_decimal", "saturating", @@ -3309,9 +3309,9 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "openssl" -version = "0.10.77" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe4646e360ec77dff7dde40ed3d6c5fee52d156ef4a62f53973d38294dad87f" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -3341,9 +3341,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.113" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2f2c0eba47118757e4c6d2bff2838f3e0523380021356e7875e858372ce644" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -3486,7 +3486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -3913,9 +3913,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -4278,7 +4278,7 @@ dependencies = [ "borsh", "bytes", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "rkyv", "serde", "serde_json", @@ -4765,9 +4765,9 @@ dependencies = [ [[package]] name = "sqlite-wasm-rs" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" +checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" dependencies = [ "cc", "js-sys", @@ -5135,9 +5135,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -5889,15 +5889,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "rand 0.8.5", + "rand 0.8.6", "static_assertions", ] [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "uncased" @@ -6071,11 +6071,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -6084,7 +6084,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -6556,6 +6556,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" From 1ba176d46b63e68680babbaf9b3b2c4f627fb1ee Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 16:00:24 +0100 Subject: [PATCH 55/79] chore(deps): bump actions/setup-node from 5 to 6 --- .github/workflows/testing.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 83a290663..173613ec3 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -56,7 +56,7 @@ jobs: - id: node name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version: "20" From cb70ca0f555f4cba95e0517443801e0d4b93502b Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 16:00:36 +0100 Subject: [PATCH 56/79] chore(deps): bump actions/github-script from 8 to 9 --- .github/workflows/upload_coverage_pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload_coverage_pr.yaml b/.github/workflows/upload_coverage_pr.yaml index 4a6c757a5..442afe31b 100644 --- a/.github/workflows/upload_coverage_pr.yaml +++ b/.github/workflows/upload_coverage_pr.yaml @@ -22,7 +22,7 @@ jobs: steps: - name: "Download existing coverage report" id: prepare_report - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | var fs = require('fs'); From 3b1e2928cd70d90e9c506edafe48e431a089be09 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 17:24:24 +0100 Subject: [PATCH 57/79] docs(issues): add issue spec for #1697 (AI agent configuration) --- docs/issues/1697-ai-agent-configuration.md | 334 +++++++++++++++++++++ project-words.txt | 9 + 2 files changed, 343 insertions(+) create mode 100644 docs/issues/1697-ai-agent-configuration.md diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md new file mode 100644 index 000000000..8e0e7b932 --- /dev/null +++ b/docs/issues/1697-ai-agent-configuration.md @@ -0,0 +1,334 @@ +# Set Up Basic AI Agent Configuration + +## Goal + +Set up the foundational configuration files in this repository to enable effective collaboration with AI coding agents. This includes adding an `AGENTS.md` file to guide agents on project conventions, adding agent skills for repeatable specialized tasks, and defining custom agents for project-specific workflows. + +## References + +- **AGENTS.md specification**: https://agents.md/ +- **Agent Skills specification**: https://agentskills.io/specification +- **GitHub Copilot — About agent skills**: https://docs.github.com/en/copilot/concepts/agents/about-agent-skills +- **GitHub Copilot — About custom agents**: https://docs.github.com/en/copilot/concepts/agents/copilot-cli/about-custom-agents + +## Background + +### AGENTS.md + +`AGENTS.md` is an open, plain-Markdown format stewarded by the [Agentic AI Foundation](https://aaif.io/) under the Linux Foundation. It acts as a "README for agents": a single, predictable file where coding agents look first for project-specific context (build steps, test commands, conventions, security considerations) that would otherwise clutter the human-focused `README.md`. + +It is supported by a wide ecosystem of tools including GitHub Copilot (VS Code), Cursor, Windsurf, OpenAI Codex, Claude Code, Jules (Google), Warp, and many others. In monorepos, nested `AGENTS.md` files can be placed inside each package; the closest file to the file being edited takes precedence. + +### Agent Skills + +Agent Skills (https://agentskills.io/specification) are directories of instructions, scripts, and resources that an agent can load to perform specialized, repeatable tasks. Each skill lives in a folder named after the skill and contains at minimum a `SKILL.md` file with YAML frontmatter (`name`, `description`, optional `license`, `compatibility`, `metadata`, `allowed-tools`) followed by Markdown instructions. + +GitHub Copilot supports: + +- **Project skills** stored in the repository at `.github/skills/`, `.claude/skills/`, or `.agents/skills/` +- **Personal skills** stored in the home directory at `~/.copilot/skills/`, `~/.claude/skills/`, or `~/.agents/skills/` + +### Custom Agents + +Custom agents are specialized versions of GitHub Copilot that can be tailored to project-specific workflows. They are defined as Markdown files with YAML frontmatter (agent profiles) stored at: + +- **Repository level**: `.github/agents/CUSTOM-AGENT-NAME.md` +- **Organization/enterprise level**: `/agents/CUSTOM-AGENT-NAME.md` inside a `.github-private` repository + +An agent profile includes a `name`, `description`, optional `tools`, and optional `mcp-servers` configurations. The Markdown body of the file acts as the agent's prompt (it is not a YAML frontmatter key). The main Copilot agent can run custom agents as subagents in isolated context windows, including in parallel. + +## Tasks + +### Task 0: Create a local branch + +- Approved branch name: `-ai-agent-configuration` +- Commands: + - `git fetch --all --prune` + - `git checkout develop` + - `git pull --ff-only` + - `git checkout -b -ai-agent-configuration` +- Checkpoint: `git branch --show-current` should output `-ai-agent-configuration`. + +--- + +### Task 1: Add `AGENTS.md` at the repository root + +Provide AI coding agents with a clear, predictable source of project context so they can work +effectively without requiring repeated manual instructions. + +**Inspiration / reference AGENTS.md files from other Torrust projects**: + +- https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/AGENTS.md +- https://raw.githubusercontent.com/torrust/torrust-linting/refs/heads/main/AGENTS.md + +Create `AGENTS.md` in the repository root, adapting the above files to the tracker. At minimum +the file must cover: + +- [ ] Repository link and project overview (language, license, MSRV, web framework, protocols, databases) +- [ ] Tech stack (languages, frameworks, databases, containerization, linting tools) +- [ ] Key directories (`src/`, `src/bin/`, `packages/`, `console/`, `contrib/`, `tests/`, `docs/`, `share/`, `storage/`, `.github/workflows/`) +- [ ] Package catalog (all workspace packages with their layer and description) +- [ ] Package naming conventions (`axum-*`, `*-server`, `*-core`, `*-protocol`) +- [ ] Key configuration files (`.markdownlint.json`, `.yamllint-ci.yml`, `.taplo.toml`, `cspell.json`, `rustfmt.toml`, etc.) +- [ ] Build & test commands (`cargo build`, `cargo test --doc`, `cargo test --all-targets`, E2E runner, benchmarks) +- [ ] Lint commands (`linter all` and individual linters; how to install the `linter` binary) +- [ ] Dependencies check (`cargo machete`) +- [ ] Code style (rustfmt rules, clippy policy, import grouping, per-format rules) +- [ ] Collaboration principles (no flattery, push back on weak ideas, flag blockers early) +- [ ] Essential rules (linting gate, GPG commit signing, no `storage/`/`target/` commits, `cargo machete`) +- [ ] Git workflow (branch naming, Conventional Commits, branch strategy: `develop` → `staging/main` → `main`) +- [ ] Development principles (observability, testability, modularity, extensibility; Beck's four rules) +- [ ] Container / Docker (key commands, ports, volume mount paths) +- [ ] Auto-invoke skills placeholder (to be filled in when `.github/skills/` is populated) +- [ ] Documentation quick-navigation table +- [ ] Add a brief entry to `docs/index.md` pointing contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/` + +Commit message: `docs(agents): add root AGENTS.md` + +Checkpoint: + +- `linter all` exits with code `0`. +- At least one AI agent (GitHub Copilot, Cursor, etc.) can be confirmed to pick up the file. + +**References**: + +- https://agents.md/ +- https://github.com/openai/codex/blob/-/AGENTS.md (real-world example) +- https://github.com/apache/airflow/blob/-/AGENTS.md (real-world monorepo example) + +--- + +### Task 2: Add Agent Skills + +Define reusable, project-specific skills that agents can load to perform specialized tasks on +this repository consistently. + +- [ ] Create `.github/skills/` directory +- [ ] Review and confirm the candidate skills listed below (add, remove, or adjust before starting implementation) +- [ ] For each skill, create a directory with: + - `SKILL.md` — YAML frontmatter (`name`, `description`, optional `license`, `compatibility`) + step-by-step instructions + - `scripts/` (optional) — executable scripts the agent can run + - `references/` (optional) — additional reference documentation +- [ ] Validate skill files against the Agent Skills spec (name rules: lowercase, hyphens, no consecutive hyphens, max 64 chars; description: max 1024 chars) + +**Candidate initial skills** (ported / adapted from `torrust-tracker-deployer`): + +The skills below are modelled on the skills already proven in +[torrust-tracker-deployer](https://github.com/torrust/torrust-tracker-deployer) +(`.github/skills/`). Deployer-specific skills (Ansible, Tera templates, LXD, SDK, +deployer CLI architecture) are excluded because they have no equivalent in the tracker. + +Directory layout to mirror the deployer structure: + +```text +.github/skills/ + add-new-skill/ + dev/ + git-workflow/ + maintenance/ + planning/ + rust-code-quality/ + testing/ +``` + +**`add-new-skill`** — meta-skill: guide for creating new Agent Skills for this repository. + +**`dev/git-workflow/`**: + +- `commit-changes` — commit following Conventional Commits; pre-commit verification checklist. +- `create-feature-branch` — branch naming convention and lifecycle. +- `open-pull-request` — open a PR via GitHub CLI or GitHub MCP tool; pre-flight checks. +- `release-new-version` — version bump, signed release commit, signed tag, CI verification. +- `review-pr` — review a PR against Torrust quality standards and checklist. +- `run-linters` — run the full linting suite (`linter all`); fix individual linter failures. +- `run-pre-commit-checks` — mandatory quality gates before every commit. + +**`dev/maintenance/`**: + +- `update-dependencies` — run `cargo update`, create branch, commit, push, open PR. + +**`dev/planning/`**: + +- `create-adr` — create an Architectural Decision Record in `docs/adrs/`. +- `create-issue` — draft and open a GitHub issue following project conventions. +- `write-markdown-docs` — GFM pitfalls (auto-links, ordered list numbering, etc.). +- `cleanup-completed-issues` — remove issue doc files and update roadmap after PR merge. + +**`dev/rust-code-quality/`**: + +- `handle-errors-in-code` — `thiserror`-based structured errors; what/where/when/why context. +- `handle-secrets` — wrapper types for tokens/passwords; never use plain `String` for secrets. + +**`dev/testing/`**: + +- `write-unit-test` — `it_should_*` naming, AAA pattern, `MockClock`, `TempDir`, `rstest`. + +Commit message: `docs(agents): add initial agent skills under .github/skills/` + +Checkpoint: + +- `linter all` exits with code `0`. +- At least one skill can be successfully activated by GitHub Copilot. + +**References**: + +- https://agentskills.io/specification +- https://docs.github.com/en/copilot/concepts/agents/about-agent-skills +- https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-skills +- https://github.com/anthropics/skills (community skills examples) +- https://github.com/github/awesome-copilot (community collection) + +--- + +### Task 3: Add Custom Agents + +Define custom GitHub Copilot agents tailored to Torrust project workflows so that specialized +tasks can be delegated to focused agents with the right prompt context. + +- [ ] Create `.github/agents/` directory +- [ ] Identify workflows that benefit from a dedicated agent (e.g. issue implementation planner, code reviewer, documentation writer, release drafter) +- [ ] For each agent, create `.github/agents/.md` with: + - YAML frontmatter: `name` (optional), `description`, optional `tools` + - Prompt body: role definition, scope, constraints, and step-by-step instructions +- [ ] Test each custom agent by assigning it to a task or issue in GitHub Copilot CLI + +**Candidate initial agents**: + +- `committer` — commit specialist: reads branch/diff, runs pre-commit checks (`linter all`), + proposes a GPG-signed Conventional Commit message, and creates the commit only after scope and + checks are clear. Reference: + [`torrust-tracker-demo/.github/agents/commiter.agent.md`](https://raw.githubusercontent.com/torrust/torrust-tracker-demo/refs/heads/main/.github/agents/commiter.agent.md) +- `issue-planner` — given a GitHub issue, produces a detailed implementation plan document (like the ones in `docs/issues/`) including branch name, task breakdown, checkpoints, and commit message suggestions +- `code-reviewer` — reviews PRs against Torrust coding conventions, clippy rules, and security considerations +- `docs-writer` — creates or updates documentation files following the existing docs structure + +Commit message: `docs(agents): add initial custom agents under .github/agents/` + +Checkpoint: + +- `linter all` exits with code `0`. +- At least one custom agent can be assigned to a task in GitHub Copilot CLI. + +**References**: + +- https://docs.github.com/en/copilot/concepts/agents/copilot-cli/about-custom-agents +- https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/create-custom-agents-for-cli +- https://docs.github.com/en/copilot/reference/customization-cheat-sheet + +--- + +### Task 4 (optional / follow-up): Add nested `AGENTS.md` files in packages + +Once the root file is stable, evaluate whether any workspace packages have sufficiently different +conventions or setup to warrant their own `AGENTS.md`. This can be tracked as a separate follow-up +issue. + +--- + +### Task 5: Add `copilot-setup-steps.yml` workflow + +Create `.github/workflows/copilot-setup-steps.yml` so that the GitHub Copilot cloud agent gets a +fully prepared development environment before it starts working on any task. Without this file, +Copilot discovers and installs dependencies itself via trial-and-error, which is slow and +unreliable. + +The workflow must contain a single `copilot-setup-steps` job (the exact job name is required by +Copilot). Steps run in GitHub Actions before Copilot starts; the file is also automatically +executed as a normal CI workflow whenever it changes, providing built-in validation. + +**Reference example** (from `torrust-tracker-deployer`): +https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.github/workflows/copilot-setup-steps.yml + +Minimum steps to include: + +- [ ] Trigger on `workflow_dispatch`, `push` and `pull_request` (scoped to the workflow file path) +- [ ] `copilot-setup-steps` job on `ubuntu-latest`, `timeout-minutes: 30`, `permissions: contents: read` +- [ ] `actions/checkout@v5` — check out the repository (verify this is still the latest stable + version on the GitHub Marketplace before merging) +- [ ] `dtolnay/rust-toolchain@stable` — install the stable Rust toolchain (pin MSRV if needed) +- [ ] `Swatinem/rust-cache@v2` — cache `target/` and `~/.cargo` between runs +- [ ] `cargo build` warm-up — build the workspace (or key packages) so incremental compilation is + ready when Copilot starts editing +- [ ] Install the `linter` binary — + `cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter` +- [ ] Install `cargo-machete` — `cargo install cargo-machete`; ensures Copilot can run unused + dependency checks (`cargo machete`) as required by the essential rules +- [ ] Smoke-check: run `linter all` to confirm the environment is healthy before Copilot begins + +Commit message: `ci(copilot): add copilot-setup-steps workflow` + +Checkpoint: + +- The workflow runs successfully via the repository's **Actions** tab (manual dispatch or push to + the file). +- `linter all` exits with code `0` inside the workflow. + +**References**: + +- https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/customize-the-agent-environment +- https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/main/.github/workflows/copilot-setup-steps.yml + +--- + +### Task 6: Create an ADR for the AI agent framework approach + +> **Note**: This task documents the decision that underlies the whole issue. It can be done +> before Tasks 1–5 if preferred — recording the decision first and then implementing it is +> the conventional ADR practice. + +Document the decision to build a custom, GitHub-Copilot-aligned agent framework (AGENTS.md + +Agent Skills + Custom Agents) rather than adopting one of the existing pre-defined agent +frameworks that were evaluated. + +**Frameworks evaluated and not adopted**: + +- [obra/superpowers](https://github.com/obra/superpowers) +- [gsd-build/get-shit-done](https://github.com/gsd-build/get-shit-done) + +**Reasons for not adopting them**: + +1. Complexity mismatch — they introduce abstractions that are heavier than what tracker + development needs. +2. Precision requirements — the tracker involves low-level programming where agent work must be + reviewed carefully; generic productivity frameworks are not designed around that constraint. +3. GitHub-first ecosystem — the tracker is hosted on GitHub and makes intensive use of GitHub + resources (Actions, Copilot, MCP tools, etc.). Staying aligned with GitHub Copilot avoids + unnecessary integration friction. +4. Tooling churn — the AI agent landscape is evolving rapidly; depending on a third-party + framework risks forced refactoring when that framework is deprecated or pivots. A first-party + approach is more stable. +5. Tailored fit — a custom solution can be shaped precisely to Torrust conventions, commit style, + linting gates, and package structure from day one. +6. Proven in practice — the same approach has already been validated during the development of + `torrust-tracker-deployer`. +7. Agent-agnostic by design — keeping the framework expressed as plain Markdown files + (AGENTS.md, SKILL.md, agent profiles) decouples it from any single agent product, making + migration or multi-agent use straightforward. +8. Incremental adoption — individual skills, custom agents, or patterns from those frameworks can + still be cherry-picked and integrated progressively if specific value is identified. + +- [ ] Create `docs/adrs/_ai-agent-framework-approach.md` using the `create-adr` skill +- [ ] Record the decision, the alternatives considered, and the reasoning above + +Commit message: `docs(adrs): add ADR for AI agent framework approach` + +Checkpoint: + +- `linter all` exits with code `0`. + +**References**: + +- `docs/adrs/README.md` — ADR naming convention for this repository +- https://adr.github.io/ + +--- + +## Acceptance Criteria + +- [ ] `AGENTS.md` exists at the repo root and contains accurate, up-to-date project guidance. +- [ ] At least one skill is available under `.github/skills/` and can be successfully activated by GitHub Copilot. +- [ ] At least one custom agent is available under `.github/agents/` and can be assigned to a task. +- [ ] `copilot-setup-steps.yml` exists, the workflow runs successfully in the **Actions** tab, and `linter all` exits with code `0` inside it. +- [ ] An ADR exists in `docs/adrs/` documenting the decision to use a custom GitHub-Copilot-aligned agent framework. +- [ ] All files pass spelling checks (`cspell`) and markdown linting. +- [ ] A brief entry in `docs/index.md` points contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/`. diff --git a/project-words.txt b/project-words.txt index 48c9565cc..6a8a264ad 100644 --- a/project-words.txt +++ b/project-words.txt @@ -36,6 +36,7 @@ clippy cloneable codecov codegen +commiter completei Condvar connectionless @@ -117,6 +118,7 @@ nonroot Norberg numwant nvCFlJCq7fz7Qx6KoKTDiMZvns8l5Kw7 +obra oneshot ostr Pando @@ -166,6 +168,7 @@ tdyne Tebibytes tempfile testcontainers +Tera thiserror tlsv Torrentstorm @@ -250,3 +253,9 @@ mysqladmin setgroups taplo trixie +adrs +Agentic +agentskills +frontmatter +MSRV +rustup From 5593dd2d9f368892f112e6a9d20dd6723fb84a9d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 18:29:37 +0100 Subject: [PATCH 58/79] docs(agents): add root AGENTS.md --- .gitignore | 1 + AGENTS.md | 388 ++++++++++++++++++++++++++++++++++++++++++++++ cspell.json | 3 +- project-words.txt | 1 + 4 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md diff --git a/.gitignore b/.gitignore index fd83ee918..4b811d59f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ codecov.json integration_tests_sqlite3.db lcov.info perf.data* +repomix-output.xml rustc-ice-*.txt diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..9ad7e360a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,388 @@ +# Torrust Tracker — AI Assistant Instructions + +**Repository**: [torrust/torrust-tracker](https://github.com/torrust/torrust-tracker) + +## 📋 Project Overview + +**Torrust Tracker** is a high-quality, production-grade BitTorrent tracker written in Rust. It +matchmakes peers and collects statistics, supporting the UDP, HTTP, and TLS socket types with +native IPv4/IPv6 support, private/whitelisted mode, and a management REST API. + +- **Language**: Rust (edition 2021, MSRV 1.72) +- **License**: AGPL-3.0-only +- **Version**: 3.0.0-develop +- **Web framework**: [Axum](https://github.com/tokio-rs/axum) +- **Async runtime**: Tokio +- **Protocols**: BitTorrent UDP (BEP 15), HTTP (BEP 3/23), REST management API +- **Databases**: SQLite3, MySQL +- **Workspace type**: Cargo workspace (multi-crate monorepo) + +## 🏗️ Tech Stack + +- **Languages**: Rust, YAML, TOML, Markdown, Shell scripts +- **Web framework**: Axum (HTTP server + REST API) +- **Async runtime**: Tokio (multi-thread) +- **Testing**: testcontainers (E2E) +- **Databases**: SQLite3, MySQL +- **Containerization**: Docker / Podman (`Containerfile`) +- **CI**: GitHub Actions +- **Linting tools**: markdownlint, yamllint, taplo, cspell, shellcheck, clippy, rustfmt (unified + under the `linter` binary from [torrust/torrust-linting](https://github.com/torrust/torrust-linting)) + +## 📁 Key Directories + +- `src/` — Main binary and library entry points (`main.rs`, `lib.rs`, `app.rs`, `container.rs`) +- `src/bin/` — Additional binary targets (`e2e_tests_runner`, `http_health_check`, `profiling`) +- `src/bootstrap/` — Application bootstrap logic +- `src/console/` — Console entry points +- `packages/` — Cargo workspace packages (all domain logic lives here; see package catalog below) +- `console/` — Console tools (e.g., `tracker-client`) +- `contrib/` — Community-contributed utilities (`bencode`) and developer tooling +- `contrib/dev-tools/` — Developer tools: git hooks (`pre-commit.sh`, `pre-push.sh`), + container scripts, and init scripts +- `tests/` — Integration tests (`integration.rs`, `servers/`) +- `docs/` — Project documentation, ADRs, issue specs, and benchmarking guides +- `docs/adrs/` — Architectural Decision Records +- `docs/issues/` — Issue specs / implementation plans +- `share/default/` — Default configuration files and fixtures +- `storage/` — Runtime data (git-ignored); databases, logs, config +- `.github/workflows/` — CI/CD workflows (testing, coverage, container, deployment) +- `.github/skills/` — Agent Skills for specialized workflows _(to be added — see issue #1697)_ +- `.github/agents/` — Custom Copilot agents _(to be added — see issue #1697)_ + +## 📦 Package Catalog + +All packages live under `packages/`. The workspace version is `3.0.0-develop`. + +| Package | Prefix / Layer | Description | +| --------------------------------- | -------------- | ------------------------------------------------ | +| `axum-server` | `axum-*` | Base Axum HTTP server infrastructure | +| `axum-http-tracker-server` | `axum-*` | BitTorrent HTTP tracker server (BEP 3/23) | +| `axum-rest-tracker-api-server` | `axum-*` | Management REST API server | +| `axum-health-check-api-server` | `axum-*` | Health monitoring endpoint | +| `http-tracker-core` | `*-core` | HTTP-specific tracker domain logic | +| `udp-tracker-core` | `*-core` | UDP-specific tracker domain logic | +| `tracker-core` | `*-core` | Central tracker peer-management logic | +| `http-protocol` | `*-protocol` | HTTP tracker protocol (BEP 3/23) parsing | +| `udp-protocol` | `*-protocol` | UDP tracker protocol (BEP 15) framing/parsing | +| `swarm-coordination-registry` | domain | Torrent/peer coordination registry | +| `configuration` | domain | Config file parsing, environment variables | +| `primitives` | domain | Core domain types (InfoHash, PeerId, …) | +| `clock` | utilities | Mockable time source for deterministic testing | +| `located-error` | utilities | Diagnostic errors with source locations | +| `test-helpers` | utilities | Mock servers, test data generation | +| `server-lib` | shared | Shared server library utilities | +| `tracker-client` | client tools | CLI tracker interaction/testing client | +| `rest-tracker-api-client` | client tools | REST API client library | +| `rest-tracker-api-core` | client tools | REST API core logic | +| `udp-tracker-server` | server | UDP tracker server implementation | +| `torrent-repository` | domain | Torrent metadata storage and InfoHash management | +| `events` | domain | Domain event definitions | +| `metrics` | domain | Prometheus metrics integration | +| `torrent-repository-benchmarking` | benchmarking | Torrent storage benchmarks | + +**Console tools** (under `console/`): + +| Tool | Description | +| ---------------- | ------------------------------------ | +| `tracker-client` | Client for interacting with trackers | + +**Community contributions** (under `contrib/`): + +| Crate | Description | +| --------- | ------------------------------- | +| `bencode` | Bencode encode/decode utilities | + +## 🏷️ Package Naming Conventions + +| Prefix | Responsibility | Dependencies | +| ------------ | -------------------------------------- | ------------------------ | +| `axum-*` | HTTP server components using Axum | Axum framework | +| `*-server` | Server implementations | Corresponding `*-core` | +| `*-core` | Domain logic and business rules | Protocol implementations | +| `*-protocol` | BitTorrent protocol implementations | BEP specifications | +| `udp-*` | UDP protocol-specific implementations | Tracker core | +| `http-*` | HTTP protocol-specific implementations | Tracker core | + +## 📄 Key Configuration Files + +| File | Used by | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `.markdownlint.json` | markdownlint | +| `.yamllint-ci.yml` | yamllint | +| `.taplo.toml` | taplo (TOML formatting) | +| `cspell.json` / `cSpell.json` | cspell (spell checker) — both filenames exist in the repo | +| `project-words.txt` | cspell project-specific dictionary | +| `rustfmt.toml` | rustfmt (`group_imports = "StdExternalCrate"`, `max_width = 130`) | +| `.cargo/config.toml` | Cargo aliases (`cov`, `cov-lcov`, `cov-html`, `time`) and global `rustflags` (`-D warnings`, `-D unused`, `-D rust-2018-idioms`, …) | +| `Cargo.toml` | Cargo workspace root | +| `compose.yaml` | Docker Compose for local dev and demo | +| `Containerfile` | Container image definition | +| `codecov.yaml` | Code coverage configuration | + +## 🧪 Build & Test + +### Setup + +```sh +rustup show # Check active toolchain +rustup update # Update toolchain +rustup toolchain install nightly # Required: pre-commit hooks use cargo +nightly fmt/check/doc +``` + +### Build + +```sh +cargo build # Build all workspace crates +cargo build --release # Release build +cargo build --package # Build a specific package +``` + +### Test + +```sh +cargo test --doc --workspace # Documentation tests +cargo test --tests --benches --examples --workspace \ + --all-targets --all-features # All tests +cargo test -p # Single package + +# MySQL-specific tests (requires a running MySQL instance) +TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true \ + cargo test --package bittorrent-tracker-core + +# Integration tests (root) +cargo test --test integration # tests/integration.rs +``` + +### E2E Tests + +```sh +cargo run --bin e2e_tests_runner -- \ + --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml" +``` + +### Documentation + +```sh +cargo +nightly doc --no-deps --bins --examples --workspace --all-features +``` + +### Benchmarks + +```sh +cargo bench --package torrent-repository-benchmarking +``` + +See [docs/benchmarking.md](docs/benchmarking.md) and [docs/profiling.md](docs/profiling.md). + +## 🔍 Lint Commands + +The project uses the `linter` binary from +[torrust/torrust-linting](https://github.com/torrust/torrust-linting). + +```sh +# Install the linter binary +cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter + +# Run all linters (MANDATORY before every commit and PR) +linter all + +# Run individual linters +linter markdown # markdownlint +linter yaml # yamllint +linter toml # taplo +linter cspell # spell checker +linter clippy # Rust linter +linter rustfmt # Rust formatter check +linter shellcheck # shell scripts +``` + +**`linter all` must exit with code `0` before every commit. PRs that fail CI linting are +rejected without review.** + +## 🔗 Dependencies Check + +```sh +cargo machete # Check for unused dependencies (mandatory before commits) +``` + +Install via: `cargo install cargo-machete` + +## 🎨 Code Style + +- **rustfmt**: Format with `cargo fmt` before committing. Config: `rustfmt.toml` + (`group_imports = "StdExternalCrate"`, `imports_granularity = "Module"`, `max_width = 130`). +- **Compile flags**: `.cargo/config.toml` enables strict global `rustflags` (`-D warnings`, + `-D unused`, `-D rust-2018-idioms`, `-D future-incompatible`, and others). All code must + compile cleanly with these flags — no suppressions unless absolutely necessary. +- **clippy**: No warnings allowed (`cargo clippy -- -D warnings`). +- **Imports**: All imports at the top of the file, grouped (std → external crates → internal + crate). Prefer short imported names over fully-qualified paths + (e.g., `Arc` not `std::sync::Arc`). Use full paths only to + disambiguate naming conflicts. +- **TOML**: Must pass `taplo fmt --check **/*.toml`. Auto-fix with `taplo fmt **/*.toml`. +- **Markdown**: Must pass markdownlint. +- **YAML**: Must pass `yamllint -c .yamllint-ci.yml`. +- **Spell checking**: Add new technical terms to `project-words.txt` (one word per line, + alphabetical order). + +## 🤝 Collaboration Principles + +These rules apply repository-wide to every assistant, including custom agents. + +When acting as an assistant in this repository: + +- Do not flatter the user or agree with weak ideas by default. +- Push back when a request, diff, or proposed commit looks wrong. +- Flag unclear but important points before they become problems. +- Ask a clarifying question instead of making a random choice when the decision matters. +- Call out likely misses: naming inconsistencies, accidental generated files, + staged-versus-unstaged mismatches, missing docs updates, or suspicious commit scope. + +When raising a likely mistake or blocker, say so clearly and early instead of burying it after +routine status updates. + +## 🔧 Essential Rules + +1. **Linting gate**: `linter all` must exit `0` before every commit. No exceptions. +2. **GPG commit signing**: All commits **must** be signed with GPG (`git commit -S`). +3. **Never commit `storage/` or `target/`**: These directories contain runtime data and build + artifacts. They are git-ignored; never force-add them. +4. **Unused dependencies**: Run `cargo machete` before committing. Remove any unused + dependencies immediately. +5. **Rust imports**: All imports at the top of the file, grouped (std → external crates → + internal crate). Prefer short imported names over fully-qualified paths. +6. **Continuous self-review**: Review your own work against project quality standards. Apply + self-review at three levels: + - **Mandatory** — before opening a pull request + - **Strongly recommended** — before each commit + - **Recommended** — after completing each small, independent, deployable change +7. **Security**: Do not report security vulnerabilities through public GitHub issues. Send an + email to `info@nautilus-cyberneering.de` instead. See [SECURITY.md](SECURITY.md). + +## 🌿 Git Workflow + +**Branch naming**: + +```text +- # e.g. 1697-ai-agent-configuration (preferred) +feat/ # for features without a tracked issue +fix/ # for bug fixes +chore/ # for maintenance tasks +``` + +**Commit messages** follow [Conventional Commits](https://www.conventionalcommits.org/): + +```text +feat(): add X +fix(): resolve Y +chore(): update Z +docs(): document W +refactor(): restructure V +ci(): adjust pipeline U +test(): add tests for T +``` + +Scope should reflect the affected package or area (e.g., `tracker-core`, `udp-protocol`, `ci`, `docs`). + +**Branch strategy**: + +- Feature branches are cut from `develop` +- PRs target `develop` +- `develop` → `staging/main` → `main` (release pipeline) +- PRs must pass all CI status checks before merge + +See [docs/release_process.md](docs/release_process.md) for the full release workflow. + +## 🧭 Development Principles + +For detailed information see [`docs/`](docs/). + +**Core Principles:** + +- **Observability**: If it happens, we can see it — even after it happens (deep traceability) +- **Testability**: Every component must be testable in isolation and as part of the whole +- **Modularity**: Clear package boundaries; servers contain only network I/O logic +- **Extensibility**: Core logic is framework-agnostic for easy protocol additions + +**Code Quality Standards** — both production and test code must be: + +- **Clean**: Well-structured with clear naming and minimal complexity +- **Maintainable**: Easy to modify and extend without breaking existing functionality +- **Readable**: Clear intent that can be understood by other developers +- **Testable**: Designed to support comprehensive testing at all levels + +**Beck's Four Rules of Simple Design** (in priority order): + +1. **Passes the tests**: The code must work as intended — testing is a first-class activity +2. **Reveals intention**: Code should be easy to understand, expressing purpose clearly +3. **No duplication**: Apply DRY — eliminating duplication drives out good designs +4. **Fewest elements**: Remove anything that doesn't serve the prior three rules + +Reference: [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.html) + +## 🐳 Container / Docker + +```sh +# Run the latest image +docker run -it torrust/tracker:latest +# or with Podman +podman run -it docker.io/torrust/tracker:latest + +# Build and run via Docker Compose +docker compose up -d # Start all services (detached) +docker compose logs -f tracker # Follow tracker logs +docker compose down # Stop and remove containers +``` + +**Volume mappings** (local `storage/` → container paths): + +```text +./storage/tracker/lib → /var/lib/torrust/tracker +./storage/tracker/log → /var/log/torrust/tracker +./storage/tracker/etc → /etc/torrust/tracker +``` + +**Ports**: UDP tracker: `6969`, HTTP tracker: `7070`, REST API: `1212` + +See [docs/containers.md](docs/containers.md) for detailed container documentation. + +## 🎯 Auto-Invoke Skills + +Agent Skills will be available under `.github/skills/` once issue #1697 is implemented. + +> Skills supplement (not replace) the rules in this file. Rules apply always; skills activate +> when their workflows are needed. + +**For VS Code**: Enable `chat.useAgentSkills` in settings to activate skill discovery. + +**Learn more**: See [Agent Skills Specification (agentskills.io)](https://agentskills.io/specification). + +## 📚 Documentation + +- [Documentation Index](docs/index.md) +- [Package Architecture](docs/packages.md) +- [Benchmarking](docs/benchmarking.md) +- [Profiling](docs/profiling.md) +- [Containers](docs/containers.md) +- [Release Process](docs/release_process.md) +- [ADRs](docs/adrs/README.md) +- [Issues / Implementation Plans](docs/issues/) +- [API docs (docs.rs)](https://docs.rs/torrust-tracker/) +- [Report a security vulnerability](SECURITY.md) + +### Quick Navigation + +| Task | Start Here | +| ------------------------------------ | ---------------------------------------------------- | +| Understand the architecture | [`docs/packages.md`](docs/packages.md) | +| Run the tracker in a container | [`docs/containers.md`](docs/containers.md) | +| Read all docs | [`docs/index.md`](docs/index.md) | +| Understand an architectural decision | [`docs/adrs/README.md`](docs/adrs/README.md) | +| Read or write an issue spec | [`docs/issues/`](docs/issues/) | +| Run benchmarks | [`docs/benchmarking.md`](docs/benchmarking.md) | +| Run profiling | [`docs/profiling.md`](docs/profiling.md) | +| Understand the release process | [`docs/release_process.md`](docs/release_process.md) | +| Report a security vulnerability | [`SECURITY.md`](SECURITY.md) | +| Agent skills reference | `.github/skills/` _(coming — see issue #1697)_ | +| Custom agents reference | `.github/agents/` _(coming — see issue #1697)_ | diff --git a/cspell.json b/cspell.json index 02f29f7f9..3b2aeb6f4 100644 --- a/cspell.json +++ b/cspell.json @@ -22,6 +22,7 @@ "contrib/bencode/benches/*.bencode", "contrib/dev-tools/su-exec/**", ".github/labels.json", - "/project-words.txt" + "/project-words.txt", + "repomix-output.xml" ] } \ No newline at end of file diff --git a/project-words.txt b/project-words.txt index 6a8a264ad..ce81bfea6 100644 --- a/project-words.txt +++ b/project-words.txt @@ -143,6 +143,7 @@ ringsize rngs rosegment routable +repomix rstest rusqlite rustc From 760fafc705e9c28bdc7e9b5a3e8c140043b6ac22 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 18:30:36 +0100 Subject: [PATCH 59/79] chore(cspell): merge cSpell.json into cspell.json --- cSpell.json | 23 ----------------------- cspell.json | 2 +- 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 cSpell.json diff --git a/cSpell.json b/cSpell.json deleted file mode 100644 index 43eb391d3..000000000 --- a/cSpell.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", - "version": "0.2", - "dictionaryDefinitions": [ - { - "name": "project-words", - "path": "./project-words.txt", - "addWords": true - } - ], - "dictionaries": [ - "project-words" - ], - "enableFiletypes": [ - "dockerfile", - "shellscript", - "toml" - ], - "ignorePaths": [ - "target", - "/project-words.txt" - ] -} \ No newline at end of file diff --git a/cspell.json b/cspell.json index 3b2aeb6f4..39ddf510e 100644 --- a/cspell.json +++ b/cspell.json @@ -25,4 +25,4 @@ "/project-words.txt", "repomix-output.xml" ] -} \ No newline at end of file +} From 03ec3bb0ac0d767341ec105ec700ea70e15b4976 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 18:37:32 +0100 Subject: [PATCH 60/79] docs(agents): add packages/AGENTS.md with package architecture guide --- packages/AGENTS.md | 152 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 packages/AGENTS.md diff --git a/packages/AGENTS.md b/packages/AGENTS.md new file mode 100644 index 000000000..d3a7dae9d --- /dev/null +++ b/packages/AGENTS.md @@ -0,0 +1,152 @@ +# Torrust Tracker — Packages + +This directory contains all Cargo workspace packages. All domain logic, protocol +implementations, server infrastructure, and utility libraries live here. + +For full project context see the [root AGENTS.md](../AGENTS.md). + +## Architecture + +Packages are organized in strict layers. Dependencies only flow downward — a package may only +depend on packages in the same layer or a lower one. + +```text +┌────────────────────────────────────────────────────────────────┐ +│ Servers (delivery layer) │ +│ axum-http-tracker-server axum-rest-tracker-api-server │ +│ axum-health-check-api-server udp-tracker-server │ +├────────────────────────────────────────────────────────────────┤ +│ Core (domain layer) │ +│ http-tracker-core udp-tracker-core tracker-core │ +│ rest-tracker-api-core swarm-coordination-registry │ +├────────────────────────────────────────────────────────────────┤ +│ Protocols │ +│ http-protocol udp-protocol │ +├────────────────────────────────────────────────────────────────┤ +│ Domain / Shared │ +│ torrent-repository configuration primitives │ +│ events metrics clock located-error server-lib │ +├────────────────────────────────────────────────────────────────┤ +│ Utilities / Test support │ +│ test-helpers located-error clock │ +└────────────────────────────────────────────────────────────────┘ +``` + +**Key architectural rule**: Servers contain only network I/O logic. All business rules live in +`*-core` packages. Protocol parsing is isolated in `*-protocol` packages. + +See [docs/packages.md](../docs/packages.md) for a full diagram. + +## Package Catalog + +### Servers (`axum-*`, `udp-tracker-server`) + +Delivery layer — accept network connections, dispatch to core handlers, return responses. +These packages must not contain business logic. + +| Package | Entry point | Protocol | +| ------------------------------ | ------------ | ----------- | +| `axum-http-tracker-server` | `src/lib.rs` | HTTP BEP 3 | +| `axum-rest-tracker-api-server` | `src/lib.rs` | REST (JSON) | +| `axum-health-check-api-server` | `src/lib.rs` | HTTP | +| `axum-server` | `src/lib.rs` | Axum base | +| `udp-tracker-server` | `src/lib.rs` | UDP BEP 15 | + +### Core (`*-core`) + +Domain layer — business rules, request validation, response building. No Axum or networking +imports. Each core package exposes a `container` module that wires up its dependencies via +dependency injection. + +| Package | Purpose | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| `tracker-core` | Central peer management: announce/scrape handlers, auth, whitelist, database abstraction (SQLite/MySQL drivers in `src/databases/driver/`) | +| `http-tracker-core` | HTTP-specific validation and response formatting | +| `udp-tracker-core` | UDP connection cookies, crypto, banning logic | +| `rest-tracker-api-core` | REST API statistics and container wiring | +| `swarm-coordination-registry` | Registry of torrents and their peer swarms | + +### Protocols (`*-protocol`) + +Strict BEP implementations — parse and serialize wire formats only. No tracker logic. + +| Package | BEP | Handles | +| --------------- | ------ | -------------------------------------------------------------- | +| `http-protocol` | BEP 3 | URL parameter parsing, bencoded responses, compact peer format | +| `udp-protocol` | BEP 15 | Message framing, connection IDs, transaction IDs | + +### Domain / Shared + +| Package | Purpose | +| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `torrent-repository` | Torrent metadata storage; InfoHash management; peer coordination | +| `configuration` | Config file parsing (`share/default/config/`) and env var loading (`TORRUST_TRACKER_CONFIG_TOML`, `TORRUST_TRACKER_CONFIG_TOML_PATH`); versioned under `src/v2_0_0/` | +| `primitives` | Core domain types: `InfoHash`, `PeerId`, `Peer`, `SwarmMetadata`, `ServiceBinding` | +| `events` | Async event bus (broadcaster / receiver / shutdown) used across packages | +| `metrics` | Prometheus-compatible metrics: counters, gauges, labels, samples | +| `server-lib` | Shared HTTP server utilities: logging, service registrar, signal handling | +| `clock` | Mockable time source — use `clock::Working` in production, `clock::Stopped` in tests | +| `located-error` | Error decorator that captures the source file/line of the original error | + +### Client Tools + +| Package | Purpose | +| ------------------------- | -------------------------------------------------------- | +| `tracker-client` | Generic HTTP and UDP tracker clients (used by E2E tests) | +| `rest-tracker-api-client` | Typed REST API client library | + +### Utilities / Test support + +| Package | Purpose | +| --------------------------------- | ---------------------------------------------------------- | +| `test-helpers` | Mock servers, test data generators, shared test fixtures | +| `torrent-repository-benchmarking` | Criterion benchmarks for alternative torrent storage impls | + +## Naming Conventions + +| Prefix / Suffix | Responsibility | May depend on | +| --------------- | ----------------------------------------- | ----------------------------- | +| `axum-*` | HTTP server components using Axum | `*-core`, Axum framework | +| `*-server` | Server implementations | Corresponding `*-core` | +| `*-core` | Domain logic and business rules | `*-protocol`, domain packages | +| `*-protocol` | BitTorrent protocol parsing/serialization | `primitives` | +| `udp-*` | UDP-specific implementations | `tracker-core` | +| `http-*` | HTTP-specific implementations | `tracker-core` | + +## Adding or Modifying a Package + +1. Create the directory under `packages//` with a `Cargo.toml` and `src/lib.rs`. +2. Add the package to the workspace `[members]` in the root `Cargo.toml`. +3. Follow the naming conventions above. +4. Each package must have: + - A crate-level doc comment in `src/lib.rs` explaining its purpose and layer. + - At minimum one unit test (doc-test acceptable for simple utility crates). +5. Run `cargo machete` after adding dependencies — unused deps must not be committed. +6. Run `linter all` before committing. + +## Testing Packages + +```sh +# All tests for a specific package +cargo test -p + +# Doc tests only +cargo test --doc -p + +# MySQL-specific tests in tracker-core (requires a running MySQL instance) +TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test -p torrust-tracker-core +``` + +Use `clock::Stopped` (from the `clock` package) in unit tests that need deterministic time. +Use `test-helpers` for mock tracker servers in integration tests. + +## Key Dependency Notes + +- `swarm-coordination-registry` is the authoritative store for peer swarms; `tracker-core` + delegates peer lookups to it. +- `configuration` is the only package that reads from the filesystem or environment at startup; + other packages receive config structs as arguments. +- `located-error` wraps any `std::error::Error` — use it at module boundaries to preserve + error origin context without losing the original error type. +- `events` provides the only sanctioned inter-package async communication channel; avoid direct + `tokio::sync` coupling between packages. From d4efa67e6765aa92c5e8d03c94cbbdae95d6632d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 18:40:08 +0100 Subject: [PATCH 61/79] docs(issues): update progress for issue #1697 task 1 --- docs/issues/1697-ai-agent-configuration.md | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index 8e0e7b932..b482e1f23 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -64,24 +64,24 @@ effectively without requiring repeated manual instructions. Create `AGENTS.md` in the repository root, adapting the above files to the tracker. At minimum the file must cover: -- [ ] Repository link and project overview (language, license, MSRV, web framework, protocols, databases) -- [ ] Tech stack (languages, frameworks, databases, containerization, linting tools) -- [ ] Key directories (`src/`, `src/bin/`, `packages/`, `console/`, `contrib/`, `tests/`, `docs/`, `share/`, `storage/`, `.github/workflows/`) -- [ ] Package catalog (all workspace packages with their layer and description) -- [ ] Package naming conventions (`axum-*`, `*-server`, `*-core`, `*-protocol`) -- [ ] Key configuration files (`.markdownlint.json`, `.yamllint-ci.yml`, `.taplo.toml`, `cspell.json`, `rustfmt.toml`, etc.) -- [ ] Build & test commands (`cargo build`, `cargo test --doc`, `cargo test --all-targets`, E2E runner, benchmarks) -- [ ] Lint commands (`linter all` and individual linters; how to install the `linter` binary) -- [ ] Dependencies check (`cargo machete`) -- [ ] Code style (rustfmt rules, clippy policy, import grouping, per-format rules) -- [ ] Collaboration principles (no flattery, push back on weak ideas, flag blockers early) -- [ ] Essential rules (linting gate, GPG commit signing, no `storage/`/`target/` commits, `cargo machete`) -- [ ] Git workflow (branch naming, Conventional Commits, branch strategy: `develop` → `staging/main` → `main`) -- [ ] Development principles (observability, testability, modularity, extensibility; Beck's four rules) -- [ ] Container / Docker (key commands, ports, volume mount paths) -- [ ] Auto-invoke skills placeholder (to be filled in when `.github/skills/` is populated) -- [ ] Documentation quick-navigation table -- [ ] Add a brief entry to `docs/index.md` pointing contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/` +- [x] Repository link and project overview (language, license, MSRV, web framework, protocols, databases) +- [x] Tech stack (languages, frameworks, databases, containerization, linting tools) +- [x] Key directories (`src/`, `src/bin/`, `packages/`, `console/`, `contrib/`, `tests/`, `docs/`, `share/`, `storage/`, `.github/workflows/`) +- [x] Package catalog (all workspace packages with their layer and description) +- [x] Package naming conventions (`axum-*`, `*-server`, `*-core`, `*-protocol`) +- [x] Key configuration files (`.markdownlint.json`, `.yamllint-ci.yml`, `.taplo.toml`, `cspell.json`, `rustfmt.toml`, etc.) +- [x] Build & test commands (`cargo build`, `cargo test --doc`, `cargo test --all-targets`, E2E runner, benchmarks) +- [x] Lint commands (`linter all` and individual linters; how to install the `linter` binary) +- [x] Dependencies check (`cargo machete`) +- [x] Code style (rustfmt rules, clippy policy, import grouping, per-format rules) +- [x] Collaboration principles (no flattery, push back on weak ideas, flag blockers early) +- [x] Essential rules (linting gate, GPG commit signing, no `storage/`/`target/` commits, `cargo machete`) +- [x] Git workflow (branch naming, Conventional Commits, branch strategy: `develop` → `staging/main` → `main`) +- [x] Development principles (observability, testability, modularity, extensibility; Beck's four rules) +- [x] Container / Docker (key commands, ports, volume mount paths) +- [x] Auto-invoke skills placeholder (to be filled in when `.github/skills/` is populated) +- [x] Documentation quick-navigation table +- [x] Add a brief entry to `docs/index.md` pointing contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/` Commit message: `docs(agents): add root AGENTS.md` From 9831b24c7eaa7a3fb61cd6f4e645947e83c38d70 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 18:44:03 +0100 Subject: [PATCH 62/79] docs(agents): add src/AGENTS.md with bootstrap wiring guide --- src/AGENTS.md | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/AGENTS.md diff --git a/src/AGENTS.md b/src/AGENTS.md new file mode 100644 index 000000000..88296f152 --- /dev/null +++ b/src/AGENTS.md @@ -0,0 +1,109 @@ +# `src/` — Binary and Library Entry Points + +This directory contains only the top-level wiring of the application: the binary entry points, +the bootstrap sequence, and the dependency-injection container. All domain logic lives in +`packages/`; this directory merely assembles and launches it. + +## File Map + +| Path | Purpose | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `main.rs` | Binary entry point. Calls `app::run()`, waits for Ctrl-C, then cancels jobs and waits for graceful shutdown. | +| `lib.rs` | Library crate root and crate-level documentation. Re-exports the public API used by integration tests and other binaries. | +| `app.rs` | `run()` and `start()` — orchestrates the full startup sequence (setup → load data from DB → start jobs). | +| `container.rs` | `AppContainer` — dependency-injection struct that holds `Arc`-wrapped instances of every per-layer container. | +| `bootstrap/app.rs` | `setup()` — loads config, validates it, initializes logging and global services, builds `AppContainer`. | +| `bootstrap/config.rs` | `initialize_configuration()` — reads config from the environment / file. | +| `bootstrap/jobs/` | One module per service: each module exposes a starter function called from `app::start_jobs`. | +| `bootstrap/jobs/manager.rs` | `JobManager` — collects `JoinHandle`s, owns the `CancellationToken`, and drives graceful shutdown. | +| `bin/e2e_tests_runner.rs` | Binary that runs E2E tests by delegating to `src/console/ci/`. | +| `bin/http_health_check.rs` | Minimal HTTP health-check binary used inside containers (avoids curl/wget dependency). | +| `bin/profiling.rs` | Binary for Valgrind / kcachegrind profiling sessions. | +| `console/` | Internal console apps (`ci/e2e`, `profiling`) used by the extra binaries above. | + +## Bootstrap Flow + +```text +main() + └─ app::run() + ├─ bootstrap::app::setup() + │ ├─ bootstrap::config::initialize_configuration() ← reads TOML / env vars + │ ├─ configuration.validate() ← panics on invalid config + │ ├─ initialize_global_services() ← logging, crypto seed + │ └─ AppContainer::initialize(&configuration) ← builds all containers + │ + └─ app::start(&config, &app_container) + ├─ load_data_from_database() ← peer keys, whitelist, metrics + └─ start_jobs() + ├─ start_swarm_coordination_registry_event_listener + ├─ start_tracker_core_event_listener + ├─ start_http_core_event_listener + ├─ start_udp_core_event_listener + ├─ start_udp_server_stats_event_listener + ├─ start_udp_server_banning_event_listener + ├─ start_the_udp_instances ← one job per configured UDP bind address + ├─ start_the_http_instances ← one job per configured HTTP bind address + ├─ start_torrent_cleanup + ├─ start_peers_inactivity_update + ├─ start_the_http_api + └─ start_health_check_api ← always started +``` + +Shutdown (`main`): receives `Ctrl-C` → calls `jobs.cancel()` (fires the `CancellationToken`) → +waits up to 10 seconds for all `JoinHandle`s to complete. + +## `AppContainer` + +`AppContainer` (`container.rs`) is a plain struct — not a framework, not a trait object tree. +It holds one `Arc<…Container>` per architectural layer: + +| Field | Layer / Package | +| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- | +| `registar` | `server-lib` — tracks active server socket registrations | +| `swarm_coordination_registry_container` | `swarm-coordination-registry` | +| `tracker_core_container` | `tracker-core` | +| `http_tracker_core_services` / `http_tracker_instance_containers` | `http-tracker-core` | +| `udp_tracker_core_services` / `udp_tracker_server_container` / `udp_tracker_instance_containers` | `udp-tracker-core` / `udp-tracker-server` | + +`AppContainer::initialize` is the only place where domain containers are constructed. +Every `bootstrap/jobs/` starter receives an `&Arc` and pulls out exactly what it +needs — no globals, no lazy statics for domain objects. + +## `JobManager` + +`JobManager` (`bootstrap/jobs/manager.rs`) is a thin wrapper around a `Vec` (each `Job` +holds a name + `JoinHandle<()>`) and a shared `CancellationToken`: + +- `push(name, handle)` — registers a job. +- `push_opt(name, handle)` — convenience for jobs that may be disabled. +- `cancel()` — fires the token; all jobs that own a clone of it will observe cancellation. +- `wait_for_all(timeout)` — joins all handles with a timeout, logging warnings for any that + exceed it. + +## Adding a New Service + +When wiring a new server or background task, follow this checklist in order: + +1. **Package** — add the new crate under `packages/` with the appropriate layer prefix. +2. **Container field** — add an `Arc` field to `AppContainer` and + initialize it inside `AppContainer::initialize`. +3. **Job launcher** — create `src/bootstrap/jobs/new_service.rs` and register it in + `src/bootstrap/jobs/mod.rs`. +4. **Wire into `app::start_jobs`** — call the new starter function and push its handle to + `job_manager`. +5. **Graceful shutdown** — ensure the new service listens for the `CancellationToken` passed + from `JobManager`. +6. **Config guard** — if the service is optional, gate the starter behind the appropriate + config field and use `push_opt`. + +## Key Rules for This Directory + +- **No domain logic here.** This directory is pure wiring. Business rules belong in `packages/`. +- **No globals for domain objects.** All state flows through `AppContainer`. +- **Startup errors panic.** `bootstrap::app::setup()` panics on invalid config or a bad crypto + seed — this is intentional (fail fast before binding ports). +- **Health check always starts.** The health-check API job is unconditional — do not gate it + behind a config flag. +- **`lib.rs` is the integration-test surface.** Integration tests import + `torrust_tracker_lib::…`. Keep the public API in `lib.rs` stable; avoid leaking internal + bootstrap details. From 0900452302da7e10b570e8496f7092823600594d Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Mon, 20 Apr 2026 19:36:47 +0100 Subject: [PATCH 63/79] docs(agents): add agent skills, pre-commit scripts, git hooks, ADR index, and templates - Add 19 agent skills under .github/skills/ covering git workflow, maintenance, planning, Rust code quality, and testing - Add scripts/pre-commit.sh: unified pre-commit check runner - Add scripts/install-git-hooks.sh: one-command git hook installer - Add .githooks/pre-commit: checked-in hook delegating to pre-commit.sh - Add docs/adrs/index.md: standalone ADR index table - Update docs/adrs/README.md: replace inline index with link to index.md - Add docs/templates/ADR.md and docs/templates/ISSUE.md - Update project-words.txt: add toplevel, behaviour, autolinks, backlinks, usize - Update docs/issues/1697-ai-agent-configuration.md: mark Task 2 complete --- .githooks/pre-commit | 7 + .github/skills/add-new-skill/SKILL.md | 146 +++++++++++++ .../add-new-skill/references/specification.md | 65 ++++++ .../dev/git-workflow/commit-changes/SKILL.md | 155 ++++++++++++++ .../create-feature-branch/SKILL.md | 113 ++++++++++ .../git-workflow/open-pull-request/SKILL.md | 73 +++++++ .../git-workflow/release-new-version/SKILL.md | 147 +++++++++++++ .../dev/git-workflow/review-pr/SKILL.md | 66 ++++++ .../dev/git-workflow/run-linters/SKILL.md | 121 +++++++++++ .../run-linters/references/linters.md | 85 ++++++++ .../run-pre-commit-checks/SKILL.md | 88 ++++++++ .../dev/maintenance/install-linter/SKILL.md | 62 ++++++ .../setup-dev-environment/SKILL.md | 123 +++++++++++ .../maintenance/update-dependencies/SKILL.md | 120 +++++++++++ .../cleanup-completed-issues/SKILL.md | 88 ++++++++ .../skills/dev/planning/create-adr/SKILL.md | 112 ++++++++++ .../skills/dev/planning/create-issue/SKILL.md | 101 +++++++++ .../dev/planning/write-markdown-docs/SKILL.md | 70 ++++++ .../handle-errors-in-code/SKILL.md | 114 ++++++++++ .../rust-code-quality/handle-secrets/SKILL.md | 87 ++++++++ .../dev/testing/write-unit-test/SKILL.md | 201 ++++++++++++++++++ docs/adrs/README.md | 27 ++- docs/adrs/index.md | 5 + docs/issues/1697-ai-agent-configuration.md | 42 ++-- docs/templates/ADR.md | 24 +++ docs/templates/ISSUE.md | 33 +++ project-words.txt | 5 + scripts/install-git-hooks.sh | 37 ++++ scripts/pre-commit.sh | 81 +++++++ 29 files changed, 2369 insertions(+), 29 deletions(-) create mode 100644 .githooks/pre-commit create mode 100644 .github/skills/add-new-skill/SKILL.md create mode 100644 .github/skills/add-new-skill/references/specification.md create mode 100644 .github/skills/dev/git-workflow/commit-changes/SKILL.md create mode 100644 .github/skills/dev/git-workflow/create-feature-branch/SKILL.md create mode 100644 .github/skills/dev/git-workflow/open-pull-request/SKILL.md create mode 100644 .github/skills/dev/git-workflow/release-new-version/SKILL.md create mode 100644 .github/skills/dev/git-workflow/review-pr/SKILL.md create mode 100644 .github/skills/dev/git-workflow/run-linters/SKILL.md create mode 100644 .github/skills/dev/git-workflow/run-linters/references/linters.md create mode 100644 .github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md create mode 100644 .github/skills/dev/maintenance/install-linter/SKILL.md create mode 100644 .github/skills/dev/maintenance/setup-dev-environment/SKILL.md create mode 100644 .github/skills/dev/maintenance/update-dependencies/SKILL.md create mode 100644 .github/skills/dev/planning/cleanup-completed-issues/SKILL.md create mode 100644 .github/skills/dev/planning/create-adr/SKILL.md create mode 100644 .github/skills/dev/planning/create-issue/SKILL.md create mode 100644 .github/skills/dev/planning/write-markdown-docs/SKILL.md create mode 100644 .github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md create mode 100644 .github/skills/dev/rust-code-quality/handle-secrets/SKILL.md create mode 100644 .github/skills/dev/testing/write-unit-test/SKILL.md create mode 100644 docs/adrs/index.md create mode 100644 docs/templates/ADR.md create mode 100644 docs/templates/ISSUE.md create mode 100755 scripts/install-git-hooks.sh create mode 100755 scripts/pre-commit.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100644 index 000000000..6e4065777 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(git rev-parse --show-toplevel)" + +"$repo_root/scripts/pre-commit.sh" \ No newline at end of file diff --git a/.github/skills/add-new-skill/SKILL.md b/.github/skills/add-new-skill/SKILL.md new file mode 100644 index 000000000..d99b4e3c9 --- /dev/null +++ b/.github/skills/add-new-skill/SKILL.md @@ -0,0 +1,146 @@ +--- +name: add-new-skill +description: Guide for creating effective Agent Skills for the torrust-tracker project. Use when you need to create a new skill (or update an existing skill) that extends AI agent capabilities with specialized knowledge, workflows, or tool integrations. Triggers on "create skill", "add new skill", "how to add skill", or "skill creation". +metadata: + author: torrust + version: "1.0" +--- + +# Creating New Agent Skills + +This skill guides you through creating effective Agent Skills for the Torrust Tracker project. + +## About Skills + +**What are Agent Skills?** + +Agent Skills are specialized instruction sets that extend AI agent capabilities with domain-specific +knowledge, workflows, and tool integrations. They follow the [agentskills.io](https://agentskills.io) +open format and work with multiple AI coding agents (Claude Code, VS Code Copilot, Cursor, Windsurf). + +### Progressive Disclosure + +Skills use a three-level loading strategy to minimize context window usage: + +1. **Metadata** (~100 tokens): `name` and `description` loaded at startup for all skills +2. **SKILL.md Body** (<5000 tokens): Loaded when a task matches the skill's description +3. **Bundled Resources**: Loaded on-demand only when referenced (scripts, references, assets) + +### When to Create a Skill vs Updating AGENTS.md + +| Use AGENTS.md for... | Use Skills for... | +| ------------------------------- | ------------------------------- | +| Always-on rules and constraints | On-demand workflows | +| "Always do X, never do Y" | Multi-step repeatable processes | +| Baseline conventions | Specialist domain knowledge | +| Rarely changes | Can be added/refined frequently | + +**Example**: "Use lowercase for skill filenames" → AGENTS.md rule. +"How to run pre-commit checks" → Skill. + +## Core Principles + +### 1. Concise is Key + +**Context window is shared** between system prompt, conversation history, other skills, +and your actual request. Only add context the agent doesn't already have. + +### 2. Set Appropriate Degrees of Freedom + +Match specificity to task fragility: + +- **High freedom** (text-based instructions): multiple approaches valid, context-dependent +- **Medium freedom** (pseudocode): preferred pattern exists, some variation acceptable +- **Low freedom** (specific scripts): operations are fragile, sequence must be followed + +### 3. Anatomy of a Skill + +A skill consists of: + +- **SKILL.md**: Frontmatter (metadata) + body (instructions) +- **Optional bundled resources**: `scripts/`, `references/`, `assets/` + +Keep SKILL.md concise (<500 lines). Move detailed content to reference files. + +### 4. Progressive Disclosure + +Split detailed content into reference files loaded on-demand: + +```markdown +## Advanced Features + +See [specification.md](references/specification.md) for Agent Skills spec. +See [patterns.md](references/patterns.md) for workflow patterns. +``` + +### 5. Content Strategy + +- **Include in SKILL.md**: essential commands and step-by-step workflows +- **Put in `references/`**: detailed descriptions, config options, troubleshooting +- **Link to official docs**: architecture docs, ADRs, contributing guides + +## Skill Creation Process + +### Step 1: Plan the Skill + +Answer: + +- What specific queries should trigger this skill? +- What tasks does it help accomplish? +- Does a similar skill already exist? + +### Step 2: Choose the Location + +Follow the directory layout: + +```text +.github/skills/ + add-new-skill/ + dev/ + git-workflow/ + maintenance/ + planning/ + rust-code-quality/ + testing/ +``` + +### Step 3: Write the SKILL.md + +Frontmatter rules: + +- `name`: lowercase letters, numbers, hyphens only; max 64 chars; no consecutive hyphens +- `description`: max 1024 chars; include trigger phrases; describe WHAT and WHEN +- `metadata.author`: `torrust` +- `metadata.version`: `"1.0"` + +### Step 4: Validate and Commit + +```bash +# Check spelling and markdown +linter cspell +linter markdown + +# Run all linters +linter all + +# Commit +git add .github/skills/ +git commit -S -m "docs(skills): add {skill-name} skill" +``` + +## Directory Layout + +```text +.github/skills/ + / + SKILL.md ← Required + references/ ← Optional: detailed docs + scripts/ ← Optional: executable scripts + assets/ ← Optional: templates, data +``` + +## References + +- Agent Skills specification: [references/specification.md](references/specification.md) +- Skill patterns: [references/patterns.md](references/patterns.md) +- Real examples: [references/examples.md](references/examples.md) diff --git a/.github/skills/add-new-skill/references/specification.md b/.github/skills/add-new-skill/references/specification.md new file mode 100644 index 000000000..90e73b8a6 --- /dev/null +++ b/.github/skills/add-new-skill/references/specification.md @@ -0,0 +1,65 @@ +# Agent Skills Specification Reference + +This document provides a reference to the Agent Skills specification from [agentskills.io](https://agentskills.io). + +## What is Agent Skills? + +Agent Skills is an open format for extending AI agent capabilities with specialized knowledge and +workflows. It's vendor-neutral and works with Claude Code, VS Code Copilot, Cursor, and Windsurf. + +## Core Concepts + +### Progressive Disclosure + +```text +Level 1: Metadata (name + description) - ~100 tokens - Loaded at startup for ALL skills +Level 2: SKILL.md body - <5000 tokens - Loaded when skill matches task +Level 3: Bundled resources - On-demand - Loaded only when referenced +``` + +### Directory Structure + +```text +.github/ +└── skills/ + └── skill-name/ + ├── SKILL.md # Required: frontmatter + instructions + ├── README.md # Optional: human-readable documentation + ├── scripts/ # Optional: executable code + ├── references/ # Optional: detailed docs loaded on-demand + └── assets/ # Optional: templates, images, data +``` + +## SKILL.md Format + +### Frontmatter (YAML) + +```yaml +--- +name: skill-name +description: | + What the skill does and when to use it. Include trigger phrases. +metadata: + author: torrust + version: "1.0" +--- +``` + +### Frontmatter Validation Rules + +**name**: + +- Required; max 64 characters +- Lowercase letters, numbers, hyphens only +- Cannot contain consecutive hyphens or XML tags + +**description**: + +- Required; max 1024 characters +- Should describe WHAT the skill does AND WHEN to use it +- Include trigger phrases/keywords + +## References + +- Official spec: +- GitHub Copilot skills docs: diff --git a/.github/skills/dev/git-workflow/commit-changes/SKILL.md b/.github/skills/dev/git-workflow/commit-changes/SKILL.md new file mode 100644 index 000000000..415ee2895 --- /dev/null +++ b/.github/skills/dev/git-workflow/commit-changes/SKILL.md @@ -0,0 +1,155 @@ +--- +name: commit-changes +description: Guide for committing changes in the torrust-tracker project. Covers conventional commit format, pre-commit verification checklist, GPG signing, and commit quality guidelines. Use when committing code, running pre-commit checks, or following project commit standards. Triggers on "commit", "commit changes", "how to commit", "pre-commit", "commit message", "commit format", or "conventional commits". +metadata: + author: torrust + version: "1.0" +--- + +# Committing Changes + +This skill guides you through the complete commit process for the Torrust Tracker project. + +## Quick Reference + +```bash +# One-time setup: install the pre-commit Git hook +./scripts/install-git-hooks.sh + +# Stage changes +git add + +# Commit with conventional format and GPG signature (MANDATORY) +# The pre-commit hook runs ./scripts/pre-commit.sh automatically +git commit -S -m "[()]: " +``` + +## Conventional Commit Format + +We follow [Conventional Commits](https://www.conventionalcommits.org/) specification. + +### Commit Message Structure + +```text +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +Scope should reflect the affected package or area (e.g., `tracker-core`, `udp-protocol`, `ci`, `docs`). + +### Commit Types + +| Type | Description | Example | +| ---------- | ------------------------------------- | ------------------------------------------------------------ | +| `feat` | New feature or enhancement | `feat(tracker-core): add peer expiry grace period` | +| `fix` | Bug fix | `fix(udp-protocol): resolve endianness in announce response` | +| `docs` | Documentation changes | `docs(agents): add root AGENTS.md` | +| `style` | Code style changes (formatting, etc.) | `style: apply rustfmt to all source files` | +| `refactor` | Code refactoring | `refactor(tracker-core): extract peer list to own module` | +| `test` | Adding or updating tests | `test(http-tracker-core): add announce response tests` | +| `chore` | Maintenance tasks | `chore: update dependencies` | +| `ci` | CI/CD related changes | `ci: add workflow for container publishing` | +| `perf` | Performance improvements | `perf(torrent-repository): switch to dashmap` | + +## GPG Commit Signing (MANDATORY) + +**All commits must be GPG signed.** Use the `-S` flag: + +```bash +git commit -S -m "your commit message" +``` + +## Pre-commit Verification (MANDATORY) + +### Git Hook + +The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh` +automatically on every `git commit`. Install it once after cloning: + +```bash +./scripts/install-git-hooks.sh +``` + +Once installed, the hook fires on every commit and you do not need to run the script manually. + +### Automated Checks + +If the hook is not installed, run the script explicitly before committing. +**It must exit with code `0`.** + +> **⏱️ Expected runtime: ~3 minutes** on a modern developer machine. AI agents must set a +> command timeout of **at least 5 minutes** before invoking this script. + +```bash +./scripts/pre-commit.sh +``` + +The script runs: + +1. `cargo machete` — unused dependency check +2. `linter all` — all linters (markdown, YAML, TOML, clippy, rustfmt, shellcheck, cspell) +3. `cargo test --doc --workspace` — documentation tests +4. `cargo test --tests --benches --examples --workspace --all-targets --all-features` — all tests + +### Manual Checks (Cannot Be Automated) + +Verify these by hand before committing: + +- **Self-review the diff**: read through `git diff --staged` and check for obvious mistakes, + debug artifacts, or unintended changes +- **Documentation updated**: if public API or behaviour changed, doc comments and any relevant + `docs/` pages reflect the change +- **`AGENTS.md` updated**: if architecture, package structure, or key workflows changed, the + relevant `AGENTS.md` file is updated +- **New technical terms added to `project-words.txt`**: any new jargon or identifiers that + cspell does not know about are added alphabetically + +### Debugging a Failing Run + +```bash +linter markdown # Markdown +linter yaml # YAML +linter toml # TOML +linter clippy # Rust code analysis +linter rustfmt # Rust formatting +linter shellcheck # Shell scripts +linter cspell # Spell checking +``` + +Fix Rust formatting automatically: + +```bash +cargo fmt +``` + +## Hashtag Usage Warning + +**Only use `#` when intentionally referencing a GitHub issue.** + +GitHub auto-links `#NUMBER` to issues. Avoid accidental references: + +- ✅ `feat(tracker-core): add feature (see #42)` — intentional reference +- ❌ `fix: make feature #1 priority` — accidentally links to issue #1 + +Use ordered Markdown lists or plain numbers instead of `#N` step labels. + +## Commit Quality Guidelines + +### Good Commits (✅) + +- **Atomic**: Each commit represents one logical change +- **Descriptive**: Clear, concise description of what changed +- **Tested**: All tests pass +- **Linted**: All linters pass +- **Conventional**: Follows conventional commit format +- **Signed**: GPG signature present + +### Commits to Avoid (❌) + +- Too large: multiple unrelated changes in one commit +- Vague messages like "fix stuff" or "WIP" +- Missing scope when a package is clearly affected +- Unsigned commits diff --git a/.github/skills/dev/git-workflow/create-feature-branch/SKILL.md b/.github/skills/dev/git-workflow/create-feature-branch/SKILL.md new file mode 100644 index 000000000..bb2c82a55 --- /dev/null +++ b/.github/skills/dev/git-workflow/create-feature-branch/SKILL.md @@ -0,0 +1,113 @@ +--- +name: create-feature-branch +description: Guide for creating feature branches following the torrust-tracker branching conventions. Covers branch naming format, lifecycle, and common patterns. Use when creating branches for issues, starting work on tasks, or setting up development branches. Triggers on "create branch", "new branch", "checkout branch", "branch for issue", or "start working on issue". +metadata: + author: torrust + version: "1.0" +--- + +# Creating Feature Branches + +This skill guides you through creating feature branches following the Torrust Tracker branching +conventions. + +## Branch Naming Convention + +**Format**: `{issue-number}-{short-description}` (preferred) + +Alternative formats (no tracked issue): + +- `feat/{short-description}` +- `fix/{short-description}` +- `chore/{short-description}` + +**Rules**: + +- Always start with the GitHub issue number when one exists +- Use lowercase letters only +- Separate words with hyphens (not underscores) +- Keep description concise but descriptive + +## Creating a Branch + +### Standard Workflow + +```bash +# Ensure you're on latest develop +git checkout develop +git pull --ff-only + +# Create and checkout branch for issue #42 +git checkout -b 42-add-peer-expiry-grace-period +``` + +### With MCP GitHub Tools + +1. Get the issue number and title +2. Format the branch name: `{number}-{kebab-case-description}` +3. Create the branch from `develop` +4. Checkout locally: `git fetch && git checkout {branch-name}` + +## Branch Naming Examples + +✅ **Good branch names**: + +- `42-add-peer-expiry-grace-period` +- `156-refactor-udp-server-socket-binding` +- `203-add-e2e-mysql-tests` +- `1697-ai-agent-configuration` + +❌ **Avoid**: + +- `my-feature` — no issue number +- `FEATURE-123` — all caps +- `fix_bug` — underscores instead of hyphens +- `42_add_support` — underscores + +## Complete Branch Lifecycle + +### 1. Create Branch from `develop` + +```bash +git checkout develop +git pull --ff-only +git checkout -b 42-add-peer-expiry-grace-period +``` + +### 2. Develop + +Make commits following [commit conventions](../commit-changes/SKILL.md). + +### 3. Pre-commit Checks + +```bash +cargo machete +linter all +cargo test --doc --workspace +cargo test --tests --benches --examples --workspace --all-targets --all-features +``` + +### 4. Push to Your Fork + +```bash +git push {your-fork-remote} 42-add-peer-expiry-grace-period +``` + +### 5. Create Pull Request + +Target branch: `torrust/torrust-tracker:develop` + +### 6. Cleanup After Merge + +```bash +git checkout develop +git pull --ff-only +git branch -d 42-add-peer-expiry-grace-period +``` + +## Converting Issue Title to Branch Name + +1. Get issue number (e.g., #42) +2. Take issue title (e.g., "Add Peer Expiry Grace Period") +3. Convert to lowercase kebab-case: `add-peer-expiry-grace-period` +4. Prefix with issue number: `42-add-peer-expiry-grace-period` diff --git a/.github/skills/dev/git-workflow/open-pull-request/SKILL.md b/.github/skills/dev/git-workflow/open-pull-request/SKILL.md new file mode 100644 index 000000000..eca0fae3b --- /dev/null +++ b/.github/skills/dev/git-workflow/open-pull-request/SKILL.md @@ -0,0 +1,73 @@ +--- +name: open-pull-request +description: Open a pull request from a feature branch using GitHub CLI (preferred) or GitHub MCP tools. Covers pre-flight checks, correct base/head configuration for fork workflows, title/body conventions, and post-creation validation. Use when asked to "open PR", "create pull request", or "submit branch for review". +metadata: + author: torrust + version: "1.0" +--- + +# Open a Pull Request + +## CLI vs MCP Decision Rule + +- **Inner loop (fast local branch work):** prefer GitHub CLI (`gh pr create`). +- **Outer loop (cross-system coordination):** use MCP tools for structured/authenticated access. + +## Pre-flight Checks + +Before opening a PR: + +- [ ] Working tree is clean (`git status`) +- [ ] Branch is pushed to your fork remote +- [ ] Commits are GPG signed (`git log --show-signature -n 1`) +- [ ] All pre-commit checks passed (`linter all`, `cargo machete`, tests) + +## Title and Description Convention + +PR title: use Conventional Commit style, include issue reference. + +Examples: + +- `feat(tracker-core): [#42] add peer expiry grace period` +- `docs(agents): set up basic AI agent configuration (#1697)` + +PR body must include: + +- Summary of changes +- Files/packages touched +- Validation performed +- Issue link (`Closes #`) + +## Option A (Preferred): GitHub CLI + +```bash +gh pr create \ + --repo torrust/torrust-tracker \ + --base develop \ + --head : \ + --title "" \ + --body "<body>" +``` + +If successful, `gh` prints the PR URL. + +## Option B: GitHub MCP Tools + +When MCP pull request management tools are available, create the PR with: + +- `base`: `develop` +- `head`: `<fork-owner>:<branch-name>` +- Capture and share the resulting PR URL. + +## Post-creation Validation + +- [ ] PR targets `torrust/torrust-tracker:develop` +- [ ] Head branch is correct +- [ ] CI workflows started +- [ ] Issue linked in description + +## Troubleshooting + +- `fatal: ... does not appear to be a git repository`: push to correct remote (`git remote -v`) +- `A pull request already exists`: open existing PR URL instead of creating new +- Permission errors on upstream: use `owner:branch` fork syntax diff --git a/.github/skills/dev/git-workflow/release-new-version/SKILL.md b/.github/skills/dev/git-workflow/release-new-version/SKILL.md new file mode 100644 index 000000000..f30898511 --- /dev/null +++ b/.github/skills/dev/git-workflow/release-new-version/SKILL.md @@ -0,0 +1,147 @@ +--- +name: release-new-version +description: Guide for releasing a new version of the Torrust Tracker using the standard staging branch, tag, and crate publication workflow. Covers version bump, release commit, staging branch promotion, PR to main, release branch/tag creation, crate publication, and merge-back to develop. Use when asked to "release", "cut a version", "publish a new version", or "create release vX.Y.Z". +metadata: + author: torrust + version: "1.0" +--- + +# Release New Version + +Primary reference: [`docs/release_process.md`](../../../../../docs/release_process.md) + +## Release Steps (Mandatory Order) + +1. Stage `develop` → `staging/main` +2. Create release commit (bump version) +3. PR `staging/main` → `main` +4. Push `main` → `releases/vX.Y.Z` +5. Create signed tag `vX.Y.Z` on that branch +6. Verify deployment workflow + crate publication +7. Create GitHub release +8. Stage `main` → `staging/develop` (merge-back) +9. Bump next dev version, PR `staging/develop` → `develop` + +Do not reorder these steps. + +## Version Naming Rules + +- Version in code: `X.Y.Z` (release) or `X.Y.Z-develop` (development) +- Git tag: `vX.Y.Z` +- Release branch: `releases/vX.Y.Z` +- Staging branches: `staging/main`, `staging/develop` + +## Pre-Flight Checklist + +Before starting: + +- [ ] Clean working tree (`git status`) +- [ ] `develop` branch is up to date with `torrust/develop` +- [ ] All CI checks pass on `develop` +- [ ] Working version in manifests is `X.Y.Z-develop` + +## Commands + +### 1) Stage develop → staging/main + +```bash +git fetch --all +git push --force torrust develop:staging/main +``` + +### 2) Create Release Commit + +```bash +git stash +git switch staging/main +git reset --hard torrust/staging/main +# Edit version in all Cargo.toml files: +# change X.Y.Z-develop → X.Y.Z +git add -A +git commit -S -m "release: version X.Y.Z" +git push torrust +``` + +Edit `version` in: + +- `Cargo.toml` (workspace) +- All packages under `packages/` that publish crates +- `console/tracker-client/Cargo.toml` +- `contrib/bencode/Cargo.toml` + +Also update any internal path dependency `version` constraints. + +### 3) PR staging/main → main + +Create PR: "Release Version X.Y.Z" (title format) +Base: `torrust/torrust-tracker:main` +Head: `staging/main` +Merge after CI passes. + +### 4) Push releases/vX.Y.Z branch + +```bash +git fetch --all +git push torrust main:releases/vX.Y.Z +``` + +### 5) Create Signed Tag + +```bash +git switch releases/vX.Y.Z +git reset --hard torrust/releases/vX.Y.Z +git tag --sign vX.Y.Z +git push --tags torrust +``` + +### 6) Verify Deployment Workflow + +Check the +[deployment workflow](https://github.com/torrust/torrust-tracker/actions/workflows/deployment.yaml) +ran successfully and the following crates were published: + +- `torrust-tracker-contrib-bencode` +- `torrust-tracker-located-error` +- `torrust-tracker-primitives` +- `torrust-tracker-clock` +- `torrust-tracker-configuration` +- `torrust-tracker-torrent-repository` +- `torrust-tracker-test-helpers` +- `torrust-tracker` + +Crates must be published in dependency order. Each must be indexed on crates.io before the next +publishes. + +### 7) Create GitHub Release + +Create a release from tag `vX.Y.Z` after the deployment workflow passes. + +### 8) Merge-back: Stage main → staging/develop + +```bash +git fetch --all +git push --force torrust main:staging/develop +``` + +### 9) Bump Next Dev Version + +```bash +git stash +git switch staging/develop +git reset --hard torrust/staging/develop +# Edit version in all Cargo.toml files: +# change X.Y.Z → (next)X.Y.Z-develop (e.g. 3.0.0 → 3.0.1-develop) +git add -A +git commit -S -m "develop: bump to version (next)X.Y.Z-develop" +git push torrust +``` + +Create PR: "Version X.Y.Z was Released" +Base: `torrust/torrust-tracker:develop` +Head: `staging/develop` + +## Failure Handling + +- **Deployment workflow failed**: fix and rerun on same release branch +- **Crate already published**: do not republish; cut a patch release +- **Partial state (tag exists but branch doesn't)**: investigate before proceeding diff --git a/.github/skills/dev/git-workflow/review-pr/SKILL.md b/.github/skills/dev/git-workflow/review-pr/SKILL.md new file mode 100644 index 000000000..da4be9ca3 --- /dev/null +++ b/.github/skills/dev/git-workflow/review-pr/SKILL.md @@ -0,0 +1,66 @@ +--- +name: review-pr +description: Review a pull request for the torrust-tracker project. Covers checklist-based PR quality verification, code style standards, test requirements, documentation, and how to submit review feedback. Use when asked to review a PR, check a pull request, or provide feedback on code changes. Triggers on "review PR", "review pull request", "check PR quality", or "code review". +metadata: + author: torrust + version: "1.0" +--- + +# Reviewing a Pull Request + +## Quick Overview Approach + +1. Read the PR title and description for context +2. Check the diff for scope of change +3. Identify the affected packages and components +4. Apply the checklist below + +## PR Review Checklist + +### PR Metadata + +- [ ] Title follows Conventional Commits format +- [ ] Description clearly explains what changes were made and why +- [ ] Issue is linked (`Closes #<number>` or `Refs #<number>`) +- [ ] Target branch is `develop` (not `main`) + +### Code Quality + +- [ ] Code follows existing patterns in affected packages +- [ ] No unused imports, variables, or functions +- [ ] No `#[allow(...)]` suppressions unless clearly justified with a comment +- [ ] Errors handled properly (use `thiserror` for structured errors, avoid `.unwrap()`) +- [ ] No security vulnerabilities (OWASP Top 10 awareness) + +### Tests + +- [ ] New functionality has unit tests +- [ ] Integration tests added if applicable +- [ ] All existing tests still pass +- [ ] Test code is clean, readable, and maintainable + +### Documentation + +- [ ] Public API items have doc comments +- [ ] `AGENTS.md` updated if architecture changed +- [ ] Markdown docs updated if user-facing behavior changed +- [ ] Spell check: new technical terms added to `project-words.txt` + +### Rust-Specific + +- [ ] Imports grouped: std → external → internal +- [ ] Line length within `max_width = 130` +- [ ] GPG-signed commits + +## Providing Feedback + +Categorize comments to help the author prioritize: + +- **Blocker** — must fix before merge (correctness, security, breaking changes) +- **Suggestion** — improvement recommended but not blocking +- **Nit** — minor style/readability point + +## Standards Reference + +All code quality standards are defined in the root `AGENTS.md`. When pointing to a +standard, reference the relevant section of `AGENTS.md`. diff --git a/.github/skills/dev/git-workflow/run-linters/SKILL.md b/.github/skills/dev/git-workflow/run-linters/SKILL.md new file mode 100644 index 000000000..c779b413f --- /dev/null +++ b/.github/skills/dev/git-workflow/run-linters/SKILL.md @@ -0,0 +1,121 @@ +--- +name: run-linters +description: Run code quality checks and linters for the torrust-tracker project. Includes Rust clippy, rustfmt, markdown, YAML, TOML, spell checking, and shellcheck. Use when asked to lint code, check formatting, fix code quality issues, or prepare for commit. Triggers on "lint", "run linters", "check code quality", "fix formatting", "run clippy", "run rustfmt", or "pre-commit checks". +metadata: + author: torrust + version: "1.0" +--- + +# Run Linters + +## Quick Reference + +### Run All Linters + +```bash +linter all +``` + +**Always run `linter all` before every commit. It must exit with code `0`.** + +### Run a Single Linter + +```bash +linter markdown # Markdown (markdownlint) +linter yaml # YAML (yamllint) +linter toml # TOML (taplo) +linter cspell # Spell checker (cspell) +linter clippy # Rust code analysis (clippy) +linter rustfmt # Rust formatting (rustfmt) +linter shellcheck # Shell scripts (shellcheck) +``` + +## Common Workflows + +### Before Any Commit + +```bash +linter all # Must pass with exit code 0 +``` + +### Debug a Failing Full Run + +```bash +# Identify which linter is failing +linter markdown +linter yaml +linter toml +linter cspell +linter clippy +linter rustfmt +linter shellcheck +``` + +### During Development (Rust only) + +```bash +linter clippy # Check logic and code quality +linter rustfmt # Check formatting +``` + +## Fixing Common Issues + +### Rust Formatting Errors (rustfmt) + +```bash +cargo fmt # Auto-fix all Rust source files +``` + +Formatting rules from `rustfmt.toml`: + +- `max_width = 130` +- `group_imports = "StdExternalCrate"` +- `imports_granularity = "Module"` + +### Rust Clippy Errors + +Warnings are **errors** (configured as `-D warnings` in `.cargo/config.toml`). +Fix the underlying issue — do not `#[allow(...)]` unless truly unavoidable. + +Example: unused variable → use `_var` prefix or actually use the value. + +### Markdown Errors (markdownlint) + +Common issues: + +- Trailing whitespace +- Missing blank line before headings +- Incorrect heading levels +- Lines exceeding 120 characters + +Configuration in `.markdownlint.json`. + +### YAML Errors (yamllint) + +Common issues: + +- Trailing spaces +- Inconsistent indentation (2 spaces expected) +- Missing newline at end of file + +Configuration in `.yamllint-ci.yml`. + +### TOML Errors (taplo) + +```bash +taplo fmt **/*.toml # Auto-fix TOML formatting +``` + +### Spell Check Errors (cspell) + +For legitimate technical terms not in dictionaries, add them to `project-words.txt` +(alphabetical order, one per line). + +### Shell Script Errors (shellcheck) + +Fix the reported issue in the shell script. Common: use `[[ ]]` instead of `[ ]`, +quote variables, avoid `eval`. + +## Linter Details + +See [references/linters.md](references/linters.md) for detailed documentation on each linter. diff --git a/.github/skills/dev/git-workflow/run-linters/references/linters.md b/.github/skills/dev/git-workflow/run-linters/references/linters.md new file mode 100644 index 000000000..11795196d --- /dev/null +++ b/.github/skills/dev/git-workflow/run-linters/references/linters.md @@ -0,0 +1,85 @@ +# Linter Documentation + +This document provides detailed documentation for each linter used in the Torrust Tracker project. + +## Overview + +The project uses the `linter` binary from +[torrust/torrust-linting](https://github.com/torrust/torrust-linting) as a unified wrapper around +all linters. + +Install: `cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter` + +## Rust Linters + +### clippy + +**Tool**: Rust's official linter. +**Config**: `.cargo/config.toml` (global `rustflags`) +**Run**: `linter clippy` + +Warnings are treated as errors via `-D warnings` in `.cargo/config.toml`. +Do not suppress warnings with `#[allow(...)]` unless absolutely necessary. + +**Critical flags** (from `.cargo/config.toml`): + +- `-D warnings` — all warnings are errors +- `-D unused` — unused items are errors +- `-D rust-2018-idioms` — enforces Rust 2018 idioms +- `-D future-incompatible` + +### rustfmt + +**Tool**: Rust code formatter. +**Config**: `rustfmt.toml` +**Run**: `linter rustfmt` +**Auto-fix**: `cargo fmt` + +Key formatting settings: + +- `max_width = 130` +- `group_imports = "StdExternalCrate"` +- `imports_granularity = "Module"` + +## Documentation Linters + +### markdownlint + +**Tool**: markdownlint +**Config**: `.markdownlint.json` +**Run**: `linter markdown` + +### cspell (Spell Checker) + +**Tool**: cspell +**Config**: `cspell.json`, `cSpell.json` +**Dictionary**: `project-words.txt` +**Run**: `linter cspell` + +Add technical terms to `project-words.txt` (alphabetical order, one per line). + +## Configuration Linters + +### yamllint + +**Tool**: yamllint +**Config**: `.yamllint-ci.yml` +**Run**: `linter yaml` + +Expected: 2-space indentation, no trailing whitespace, newline at EOF. + +### taplo + +**Tool**: taplo +**Config**: `.taplo.toml` +**Run**: `linter toml` +**Auto-fix**: `taplo fmt **/*.toml` + +## Script Linters + +### shellcheck + +**Tool**: shellcheck +**Run**: `linter shellcheck` + +Checks all shell scripts. Use `[[ ]]` over `[ ]`, quote variables (`"$var"`), and avoid `eval`. diff --git a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md new file mode 100644 index 000000000..8e19eee0e --- /dev/null +++ b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md @@ -0,0 +1,88 @@ +--- +name: run-pre-commit-checks +description: Run all mandatory pre-commit verification steps for the torrust-tracker project. Covers the pre-commit script (automated checks), manual review steps, and individual linter commands for debugging. Use before any commit or PR to ensure all quality gates pass. Triggers on "pre-commit checks", "run all checks", "verify before commit", or "check everything". +metadata: + author: torrust + version: "1.0" +--- + +# Run Pre-commit Checks + +## Git Hook (Recommended Setup) + +The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh` +automatically on every `git commit`. Install it once after cloning: + +```bash +./scripts/install-git-hooks.sh +``` + +After installation the hook fires automatically; you do not need to invoke the script +manually before each commit. + +## Automated Checks + +> **⏱️ Expected runtime: ~3 minutes** on a modern developer machine. AI agents must set a +> command timeout of **at least 5 minutes** before invoking `./scripts/pre-commit.sh`. Agents +> with a default per-command timeout below 5 minutes will likely time out and report a false +> failure. + +Run the pre-commit script. **It must exit with code `0` before every commit.** + +```bash +./scripts/pre-commit.sh +``` + +The script runs these steps in order: + +1. `cargo machete` — unused dependency check +2. `linter all` — all linters (markdown, YAML, TOML, clippy, rustfmt, shellcheck, cspell) +3. `cargo test --doc --workspace` — documentation tests +4. `cargo test --tests --benches --examples --workspace --all-targets --all-features` — all tests + +> **MySQL tests**: MySQL-specific tests require a running instance and a feature flag: +> +> ```bash +> TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test --package tracker-core +> ``` +> +> These are not run by the pre-commit script. + +## Manual Checks (Cannot Be Automated) + +Verify these by hand before committing: + +- **Self-review the diff**: read through `git diff --staged` for debug artifacts or unintended changes +- **Documentation updated**: if public API or behaviour changed, doc comments and `docs/` pages reflect it +- **`AGENTS.md` updated**: if architecture or key workflows changed, the relevant `AGENTS.md` is updated +- **New technical terms in `project-words.txt`**: new jargon added alphabetically + +## Before Opening a PR (Recommended) + +```bash +cargo +nightly doc --no-deps --bins --examples --workspace --all-features +``` + +## Debugging Individual Linters + +Run individual linters to isolate a failure: + +```bash +linter markdown # Markdown +linter yaml # YAML +linter toml # TOML +linter clippy # Rust code analysis +linter rustfmt # Rust formatting +linter shellcheck # Shell scripts +linter cspell # Spell checking +``` + +| Failure | Fix | +| ------------------- | --------------------------------------- | +| Unused dependency | Remove from `Cargo.toml` | +| Clippy warning | Fix the underlying issue | +| rustfmt error | Run `cargo fmt` | +| Markdown lint error | Fix formatting per `.markdownlint.json` | +| Spell check error | Add term to `project-words.txt` | +| Test failure | Fix the failing test or code | +| Doc build error | Fix Rust doc comment | diff --git a/.github/skills/dev/maintenance/install-linter/SKILL.md b/.github/skills/dev/maintenance/install-linter/SKILL.md new file mode 100644 index 000000000..9112acd31 --- /dev/null +++ b/.github/skills/dev/maintenance/install-linter/SKILL.md @@ -0,0 +1,62 @@ +--- +name: install-linter +description: Install the torrust-linting `linter` binary and its external tool dependencies. Use when setting up a new development environment, after a fresh clone, or when the `linter` binary is missing. Triggers on "install linter", "setup linter", "linter not found", "install torrust-linting", "missing linter binary", or "set up development environment". +metadata: + author: torrust + version: "1.0" +--- + +# Install the Linter + +The project uses a unified `linter` binary from +[torrust/torrust-linting](https://github.com/torrust/torrust-linting) to run all quality checks. + +## Install the `linter` Binary + +```bash +cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter +``` + +Verify the installation: + +```bash +linter --version +``` + +## Install External Tool Dependencies + +The `linter` binary delegates to external tools. Install them if they are not already present: + +| Linter | Tool | Install command | +| ----------- | ---------------- | ------------------------------------- | +| Markdown | markdownlint-cli | `npm install -g markdownlint-cli` | +| YAML | yamllint | `pip3 install yamllint` | +| TOML | taplo | `cargo install taplo-cli --locked` | +| Spell check | cspell | `npm install -g cspell` | +| Shell | shellcheck | `apt install shellcheck` | +| Rust | clippy / rustfmt | bundled with `rustup` (no extra step) | + +> The `linter` binary will attempt to install missing npm-based tools automatically on first run. +> System-packaged tools (`yamllint`, `shellcheck`) must be installed manually. + +## Configuration Files + +The linters read configuration from files in the project root. These are already present in the +repository — no manual setup is needed: + +| File | Used by | +| -------------------- | ------------ | +| `.markdownlint.json` | markdownlint | +| `.yamllint-ci.yml` | yamllint | +| `.taplo.toml` | taplo | +| `cspell.json` | cspell | + +## Verify Full Setup + +After installing the binary and its dependencies, run all linters to confirm everything works: + +```bash +linter all +``` + +It must exit with code `0`. See the `run-linters` skill for day-to-day usage. diff --git a/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md b/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md new file mode 100644 index 000000000..1228611b5 --- /dev/null +++ b/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md @@ -0,0 +1,123 @@ +--- +name: setup-dev-environment +description: Set up a local development environment for torrust-tracker from scratch. Covers system dependencies, Rust toolchain, storage directories, linter binary, git hooks, and smoke tests. Use when onboarding to the project, setting up a new machine, or after a fresh clone. Triggers on "setup dev environment", "fresh clone", "onboarding", "install dependencies", "set up environment", or "getting started". +metadata: + author: torrust + version: "1.0" +--- + +# Set Up the Development Environment + +Full setup guide for a fresh clone of `torrust-tracker`. Follow the steps in order. + +Reference: [How to Set Up the Development Environment](https://torrust.com/blog/how-to-setup-the-development-environment) + +## Step 1: System Dependencies + +Install the required system packages (Debian/Ubuntu): + +```bash +sudo apt-get install libsqlite3-dev pkg-config libssl-dev make +``` + +> For other distributions, install the equivalent packages for SQLite3 development headers, OpenSSL +> development headers, `pkg-config`, and `make`. + +## Step 2: Rust Toolchain + +```bash +rustup show # Confirm toolchain is active +rustup update # Update to latest stable +rustup toolchain install nightly # Required for docs generation +``` + +The project MSRV is **1.72**. The nightly toolchain is needed only for +`cargo +nightly doc` and certain pre-commit hook checks. + +## Step 3: Build + +```bash +cargo build +``` + +This compiles all workspace crates and verifies that all dependencies resolve correctly. + +## Step 4: Create Storage Directories + +The tracker writes runtime data (databases, logs, TLS certs, config) to `storage/`, which is +git-ignored. Create the required folders once: + +```bash +mkdir -p ./storage/tracker/lib/database +mkdir -p ./storage/tracker/lib/tls +mkdir -p ./storage/tracker/etc +``` + +## Step 5: Install the Linter Binary + +```bash +cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter +``` + +See the `install-linter` skill for external tool dependencies (markdownlint, yamllint, etc.). + +## Step 6: Install Additional Cargo Tools + +```bash +cargo install cargo-machete # Unused dependency checker +``` + +## Step 7: Install Git Hooks + +Install the project pre-commit hook (one-time, re-run after hook changes): + +```bash +./scripts/install-git-hooks.sh +``` + +The hook runs `./scripts/pre-commit.sh` automatically on every `git commit`. + +## Step 8: Smoke Test + +Run the tracker with the default development configuration to confirm the build works: + +```bash +cargo run +``` + +Expected output includes lines like: + +```text +Loading configuration from default configuration file: `./share/default/config/tracker.development.sqlite3.toml` +[UDP TRACKER] Starting on: udp://0.0.0.0:6969 +[HTTP TRACKER] Started on: http://0.0.0.0:7070 +[API] Started on http://127.0.0.1:1212 +[HEALTH CHECK API] Started on: http://127.0.0.1:1313 +``` + +Press `Ctrl-C` to stop. + +## Step 9: Verify Full Test Suite + +```bash +cargo test --doc --workspace +cargo test --tests --benches --examples --workspace --all-targets --all-features +``` + +Both commands must exit `0` before any commit. + +## Custom Configuration (Optional) + +To run with a custom config instead of the default template: + +```bash +cp share/default/config/tracker.development.sqlite3.toml storage/tracker/etc/tracker.toml +# Edit storage/tracker/etc/tracker.toml as needed +TORRUST_TRACKER_CONFIG_TOML_PATH="./storage/tracker/etc/tracker.toml" cargo run +``` + +## Useful Development Tools + +- **DB Browser for SQLite** — inspect and edit SQLite databases: <https://sqlitebrowser.org/> +- **qBittorrent** — BitTorrent client for manual testing: <https://www.qbittorrent.org/> +- **imdl** — torrent file editor (`cargo install imdl`): <https://github.com/casey/intermodal> diff --git a/.github/skills/dev/maintenance/update-dependencies/SKILL.md b/.github/skills/dev/maintenance/update-dependencies/SKILL.md new file mode 100644 index 000000000..c0aa1c867 --- /dev/null +++ b/.github/skills/dev/maintenance/update-dependencies/SKILL.md @@ -0,0 +1,120 @@ +--- +name: update-dependencies +description: Guide for updating project dependencies in the torrust-tracker project. Covers the manual cargo update workflow including branch creation, running checks, committing, and pushing. Distinguishes trivial updates (Cargo.lock only) from breaking-change updates (code rework needed). Use when updating dependencies, running cargo update, or bumping deps. Triggers on "update dependencies", "cargo update", "update deps", or "bump dependencies". +metadata: + author: torrust + version: "1.0" +--- + +# Updating Dependencies + +This skill guides you through updating project dependencies for the Torrust Tracker project. + +## Update Categories + +Before starting, decide which category the update falls into: + +| Category | Description | Branch / Issue | +| ------------ | -------------------------------------------- | -------------------------------------------------------------- | +| **Trivial** | `cargo update` only — no code changes needed | Timestamped branch, no issue required | +| **Breaking** | Dependency change requires code rework | If small: same branch. If large: open a separate issue per dep | + +Use `cargo update --dry-run` or read the dependency changelog to classify before starting. + +## Quick Reference + +```bash +# Get a timestamp (YYYYMMDD) +TIMESTAMP=$(date +%Y%m%d) + +# Create branch +git checkout develop && git pull --ff-only +git checkout -b "${TIMESTAMP}-update-dependencies" + +# Update dependencies +cargo update 2>&1 | tee /tmp/cargo-update.txt + +# If Cargo.lock has no changes, nothing to do — stop here. + +# Verify +./scripts/pre-commit.sh + +# Commit and push +git add Cargo.lock +git commit -S -m "chore: update dependencies" -m "$(cat /tmp/cargo-update.txt)" +git push {your-fork-remote} "${TIMESTAMP}-update-dependencies" +``` + +## Complete Workflow + +### Step 1: Create a Branch + +Generate a timestamp prefix to avoid branch name conflicts across repeated runs: + +```bash +TIMESTAMP=$(date +%Y%m%d) +git checkout develop +git pull --ff-only +git checkout -b "${TIMESTAMP}-update-dependencies" +``` + +For breaking-change updates that require a tracked issue: + +```bash +git checkout -b {issue-number}-update-dependencies +``` + +### Step 2: Run Cargo Update + +```bash +cargo update 2>&1 | tee /tmp/cargo-update.txt +``` + +If `Cargo.lock` has no changes, there is nothing to update — exit early. + +Review `/tmp/cargo-update.txt` to identify any major version bumps that may be breaking. + +### Step 3: Handle Breaking Changes + +If any updated dependency introduced a breaking API change: + +- **Small rework** (a few lines, no design decisions): fix it in this branch and continue. +- **Large rework** (architectural impact or significant effort): revert that specific dependency + in `Cargo.toml`, keep the other trivial updates, and open a new issue for the breaking + dependency separately. + +```bash +# Revert a single crate to its current locked version to defer it +cargo update --precise {old-version} {crate-name} +``` + +### Step 4: Verify + +```bash +cargo machete +./scripts/pre-commit.sh +``` + +Fix any failures before proceeding. + +### Step 5: Commit and Push + +```bash +git add Cargo.lock +git commit -S -m "chore: update dependencies" -m "$(cat /tmp/cargo-update.txt)" +git push {your-fork-remote} "${TIMESTAMP}-update-dependencies" +``` + +### Step 6: Open PR + +Target: `torrust/torrust-tracker:develop` +Title: `chore: update dependencies` + +## Decision Guide + +| Scenario | Action | +| ---------------------------------------------- | ---------------------------------------------------------- | +| `cargo update` with no code changes | Trivial — timestamped branch, no issue | +| Breaking change, small rework (< 1 hour) | Fix in the same branch, note in PR description | +| Breaking change, large rework (> 1 hour) | Defer: revert that dep, open a separate issue, separate PR | +| Multiple breaking deps, independent migrations | One issue + PR per dependency to keep diffs reviewable | diff --git a/.github/skills/dev/planning/cleanup-completed-issues/SKILL.md b/.github/skills/dev/planning/cleanup-completed-issues/SKILL.md new file mode 100644 index 000000000..a4c7b3966 --- /dev/null +++ b/.github/skills/dev/planning/cleanup-completed-issues/SKILL.md @@ -0,0 +1,88 @@ +--- +name: cleanup-completed-issues +description: Guide for cleaning up completed and closed issues in the torrust-tracker project. Covers removing issue documentation files from docs/issues/ and committing the cleanup. Supports single issue cleanup or batch cleanup. Use when cleaning up closed issues, removing issue docs, or maintaining the docs/issues/ folder. Triggers on "cleanup issue", "remove issue", "clean completed issues", "delete closed issue", or "maintain issue docs". +metadata: + author: torrust + version: "1.0" +--- + +# Cleaning Up Completed Issues + +## When to Clean Up + +- **After PR merge**: Remove the issue file when its PR is merged +- **Batch cleanup**: Periodically clean up multiple closed issues during maintenance +- **Before releases**: Tidy documentation before major releases + +## Cleanup Approaches + +### Option 1: Single Issue Cleanup (Recommended) + +1. Verify the issue is closed on GitHub +2. Remove the issue file from `docs/issues/` +3. Commit and push changes + +### Option 2: Batch Cleanup + +1. List all issue files in `docs/issues/` +2. Check status of each issue on GitHub +3. Remove all closed issue files +4. Commit and push with a descriptive message + +## Step-by-Step Process + +### Step 1: Verify Issue is Closed on GitHub + +**Single issue:** + +```bash +gh issue view {issue-number} --json state --jq .state +``` + +Expected: `CLOSED` + +**Batch:** + +```bash +for issue in 21 22 23 24; do + state=$(gh issue view "$issue" --json state --jq .state 2>/dev/null || echo "NOT_FOUND") + echo "$issue:$state" +done +``` + +### Step 2: Remove Issue Documentation File + +```bash +# Single issue +git rm docs/issues/42-add-peer-expiry-grace-period.md + +# Batch +git rm docs/issues/21-some-old-issue.md \ + docs/issues/22-another-old-issue.md +``` + +### Step 3: Commit and Push + +```bash +# Single issue +git commit -S -m "chore(issues): remove closed issue #42 documentation" + +# Batch +git commit -S -m "chore(issues): remove documentation for closed issues #21, #22, #23" + +git push {your-fork-remote} {branch} +``` + +## Determining If an Issue File Should Stay + +Keep issue files when: + +- The issue is still open +- The PR is open (still being worked on) +- The specification is referenced from other active docs + +Remove issue files when: + +- The issue is **closed** +- The implementing PR is **merged** +- The file is no longer referenced by active work diff --git a/.github/skills/dev/planning/create-adr/SKILL.md b/.github/skills/dev/planning/create-adr/SKILL.md new file mode 100644 index 000000000..930a4bfc9 --- /dev/null +++ b/.github/skills/dev/planning/create-adr/SKILL.md @@ -0,0 +1,112 @@ +--- +name: create-adr +description: Guide for creating Architectural Decision Records (ADRs) in the torrust-tracker project. Covers the timestamp-based file naming convention, free-form structure, index registration in the docs/adrs/README.md index table, and commit workflow. Use when documenting architectural decisions, recording design choices, or adding decision records. Triggers on "create ADR", "add ADR", "new decision record", "architectural decision", "document decision", or "add decision". +metadata: + author: torrust + version: "1.0" +--- + +# Creating Architectural Decision Records + +## Quick Reference + +```bash +# 1. Generate the filename prefix +date -u +"%Y%m%d%H%M%S" +# e.g. 20241115093012 + +# 2. Create the ADR file +# Format: YYYYMMDDHHMMSS_snake_case_title.md +touch docs/adrs/20241115093012_your_decision_title.md + +# 3. Update the index +# Add entry to docs/adrs/index.md + +# 4. Validate and commit +linter markdown +linter cspell +git commit -S -m "docs(adrs): add ADR for {short description}" +``` + +## When to Create an ADR + +Create an ADR when making a decision that: + +- Affects the project's architecture or design patterns +- Chooses one approach over alternatives that were considered +- Has consequences worth documenting for future contributors +- Answers "why was this done this way?" + +Do **not** create an ADR for trivial implementation choices or style preferences covered by linting. + +## File Naming Convention + +**Format**: `YYYYMMDDHHMMSS_snake_case_title.md` + +Generate the timestamp prefix: + +```bash +date -u +"%Y%m%d%H%M%S" +``` + +**Examples**: + +- `20240227164834_use_plural_for_modules_containing_collections.md` +- `20241115093012_adopt_axum_for_http_server.md` + +Location: `docs/adrs/` + +## ADR Structure + +There is no rigid template — derive structure from context. Use +[docs/templates/ADR.md](../../../docs/templates/ADR.md) as a starting point. + +Optional sections to add when relevant: + +- **Alternatives Considered**: other options explored and why they were rejected +- **Consequences**: positive and negative effects of the decision + +## Step-by-Step Process + +### Step 1: Generate Filename + +```bash +PREFIX=$(date -u +"%Y%m%d%H%M%S") +TITLE="your_decision_title" # snake_case +echo "docs/adrs/${PREFIX}_${TITLE}.md" +``` + +### Step 2: Write the ADR + +- **Description**: Explain the problem thoroughly — enough context for future contributors +- **Agreement**: State clearly what was decided and why +- **Date**: Today's date (`date -u +"%Y-%m-%d"`) +- **References**: Issues, PRs, external docs + +### Step 3: Update the Index + +Add a row to the index table in `docs/adrs/index.md`: + +```markdown +| [YYYYMMDDHHMMSS](YYYYMMDDHHMMSS_your_title.md) | YYYY-MM-DD | Short Title | One-sentence description. | +``` + +- The first column links to the ADR file using the timestamp as display text. +- The short description should allow a reader to understand the decision without opening the file. + +### Step 4: Validate and Commit + +```bash +linter markdown +linter cspell +linter all # full check + +git add docs/adrs/ +git commit -S -m "docs(adrs): add ADR for {short description}" +git push {your-fork-remote} {branch} +``` + +## Example ADR + +For a real example, see +[20240227164834_use_plural_for_modules_containing_collections.md](../../../docs/adrs/20240227164834_use_plural_for_modules_containing_collections.md). diff --git a/.github/skills/dev/planning/create-issue/SKILL.md b/.github/skills/dev/planning/create-issue/SKILL.md new file mode 100644 index 000000000..ed38c9933 --- /dev/null +++ b/.github/skills/dev/planning/create-issue/SKILL.md @@ -0,0 +1,101 @@ +--- +name: create-issue +description: Guide for creating GitHub issues in the torrust-tracker project. Covers the full workflow from specification drafting, user review, to GitHub issue creation with proper documentation and file naming. Supports task, bug, feature, and epic issue types. Use when creating issues, opening tickets, filing bugs, proposing tasks, or adding features. Triggers on "create issue", "open issue", "new issue", "file bug", "add task", "create epic", or "open ticket". +metadata: + author: torrust + version: "1.0" +--- + +# Creating Issues + +## Issue Types + +| Type | Label | When to Use | +| ----------- | --------- | -------------------------------------------- | +| **Task** | `task` | Single implementable unit of work | +| **Bug** | `bug` | Something broken that needs fixing | +| **Feature** | `feature` | New capability or enhancement | +| **Epic** | `epic` | Major feature area containing multiple tasks | + +## Workflow Overview + +The process is **spec-first**: write and review a specification before creating the GitHub issue. + +1. **Draft specification** document in `docs/issues/` (no template — write from scratch) +2. **User reviews** the draft specification +3. **Create GitHub issue** +4. **Rename spec file** to include the issue number +5. **Pre-commit checks** and commit the spec + +**Never create the GitHub issue before the user reviews and approves the specification.** + +## Step-by-Step Process + +### Step 1: Draft Issue Specification + +Create a specification file with a **temporary name** (no issue number yet): + +```bash +touch docs/issues/{short-description}.md +``` + +Use [docs/templates/ISSUE.md](../../../docs/templates/ISSUE.md) as the starting structure. +Use **placeholders** for the issue number until after creation (e.g., `[To be assigned]`). + +After drafting, run linters: + +```bash +linter markdown +linter cspell +``` + +### Step 2: User Reviews the Draft + +**STOP HERE** — present the draft to the user. Iterate until approved. + +### Step 3: Create the GitHub Issue + +After user approval, create the GitHub issue. Options: + +**GitHub CLI:** + +```bash +gh issue create \ + --repo torrust/torrust-tracker \ + --title "{title}" \ + --body "{body}" \ + --label "{label}" +``` + +**MCP GitHub tools** (if available): use `mcp_github_github_issue_write` with `title`, `body`, and `labels`. + +### Step 4: Rename the Spec File + +Rename using the assigned issue number: + +```bash +git mv docs/issues/{short-description}.md \ + docs/issues/{number}-{short-description}.md +``` + +Update any issue number placeholders inside the file. + +### Step 5: Commit and Push + +```bash +linter all # Must pass + +git add docs/issues/ +git commit -S -m "docs(issues): add issue specification for #{number}" +git push {your-fork-remote} {branch} +``` + +## Naming Convention + +File name format: `{number}-{short-description}.md` + +Examples: + +- `1697-ai-agent-configuration.md` +- `42-add-peer-expiry-grace-period.md` +- `523-internal-linting-tool.md` diff --git a/.github/skills/dev/planning/write-markdown-docs/SKILL.md b/.github/skills/dev/planning/write-markdown-docs/SKILL.md new file mode 100644 index 000000000..a2c166efa --- /dev/null +++ b/.github/skills/dev/planning/write-markdown-docs/SKILL.md @@ -0,0 +1,70 @@ +--- +name: write-markdown-docs +description: Guide for writing Markdown documentation in this project. Covers GitHub Flavored Markdown pitfalls, especially the critical #NUMBER pattern that auto-links to GitHub issues and PRs (NEVER use #1, #2, #3 as step/list numbers). Use ordered lists or plain numbers instead. Covers intentional vs accidental autolinks for issues, @mentions, and commit SHAs. Use when writing .md files, documentation, issue descriptions, PR descriptions, or README updates. Triggers on "markdown", "write docs", "documentation", "#number", "github markdown", "autolink", "markdown pitfall", or "GFM". +metadata: + author: torrust + version: "1.0" +--- + +# Writing Markdown Documentation + +## Critical: #NUMBER Auto-links to GitHub Issues + +**GitHub automatically converts `#NUMBER` → link to issue/PR/discussion.** + +```markdown +❌ Bad: accidentally links to issues + +- Task #1: Set up infrastructure ← links to GitHub issue #1 +- Task #2: Configure database ← links to GitHub issue #2 + +Step #1: Install dependencies ← links to GitHub issue #1 +``` + +The links pollute the referenced issues with unrelated backlinks and confuse readers. + +### Fix: Use Ordered Lists or Plain Numbers + +```markdown +✅ Solution 1: Ordered list (automatic numbering) + +1. Set up infrastructure +2. Configure database +3. Deploy application + +✅ Solution 2: Plain numbers (no hash) + +- Task 1: Set up infrastructure +- Task 2: Configure database + +✅ Solution 3: Alternative formats + +- Task (1): Set up infrastructure +- Task [1]: Set up infrastructure +``` + +## When #NUMBER IS Intentional + +Use `#NUMBER` only when you explicitly want to link to that GitHub issue/PR: + +```markdown +✅ Intentional: referencing issue +This implements the behavior described in #42. +Closes #1697. +``` + +## Other GFM Auto-links to Know + +```markdown +@username → links to GitHub user profile (use intentionally for mentions) +abc1234 (SHA) → links to commit (useful for references) +owner/repo#42 → cross-repo issue link +``` + +## Checklist Before Committing Docs + +- [ ] No `#NUMBER` patterns used for enumeration or step numbering +- [ ] Ordered lists use Markdown syntax (`1.` `2.` `3.`) +- [ ] Any `#NUMBER` present is an intentional issue/PR reference +- [ ] Tables are consistently formatted +- [ ] `linter markdown` and `linter cspell` pass diff --git a/.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md b/.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md new file mode 100644 index 000000000..7b326ce60 --- /dev/null +++ b/.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md @@ -0,0 +1,114 @@ +--- +name: handle-errors-in-code +description: Guide for error handling in this Rust project. Covers the four principles (clarity, context, actionability, explicit enums over anyhow), the thiserror pattern for structured errors, including what/where/when/why context, writing actionable help text, and avoiding vague errors. Also covers the located-error package for errors with source location. Use when writing error types, handling Results, adding error variants, or reviewing error messages. Triggers on "error handling", "error type", "Result", "thiserror", "anyhow", "error enum", "error message", "handle error", "add error variant", or "located-error". +metadata: + author: torrust + version: "1.0" +--- + +# Handling Errors in Code + +## Core Principles + +1. **Clarity** — Users immediately understand what went wrong +2. **Context** — Include what/where/when/why +3. **Actionability** — Tell users how to fix it +4. **Explicit enums over `anyhow`** — Prefer structured errors for pattern matching + +## Prefer Explicit Enum Errors + +```rust +// ✅ Correct: explicit, matchable, clear +#[derive(Debug, thiserror::Error)] +pub enum TrackerError { + #[error("Torrent '{info_hash}' not found in whitelist")] + TorrentNotWhitelisted { info_hash: InfoHash }, + + #[error("Peer limit exceeded for torrent '{info_hash}': max {limit}")] + PeerLimitExceeded { info_hash: InfoHash, limit: usize }, +} + +// ❌ Wrong: opaque, hard to match +return Err(anyhow::anyhow!("Something went wrong")); +return Err("Invalid input".into()); +``` + +## Include Actionable Fix Instructions in Display + +When the error is user-facing, add instructions: + +```rust +#[error( + "Configuration file not found at '{path}'.\n\ + Copy the default: cp share/default/config/tracker.toml {path}" +)] +ConfigNotFound { path: PathBuf }, +``` + +## Context Requirements + +Each error should answer: + +- **What**: What operation was being performed? +- **Where**: Which component, file, or resource? +- **When**: Under what conditions? +- **Why**: What caused the failure? + +```rust +// ✅ Good: full context +#[error("UDP socket bind failed for '{addr}': {source}. Is port {port} already in use?")] +SocketBindFailed { addr: SocketAddr, port: u16, source: std::io::Error }, + +// ❌ Bad: no context +return Err("bind failed".into()); +``` + +## The `located-error` Package + +For errors that benefit from source location tracking, use the `located-error` package: + +```toml +[dependencies] +torrust-tracker-located-error = { workspace = true } +``` + +```rust +use torrust_tracker_located_error::Located; + +// Wraps any error with file and line information +let err = Located(my_error).into(); +``` + +## Unwrap and Expect Policy + +| Context | `.unwrap()` | `.expect("msg")` | `?` / `Result` | +| ---------------------- | ----------- | ----------------------------------------- | -------------- | +| Production code | Never | Only when failure is logically impossible | Default | +| Tests and doc examples | Acceptable | Preferred when message adds clarity | — | + +```rust +// ✅ Production: propagate errors with ? +fn load_config(path: &Path) -> Result<Config, ConfigError> { + let content = std::fs::read_to_string(path) + .map_err(|e| ConfigError::FileAccess { path: path.to_path_buf(), source: e })?; + toml::from_str(&content) + .map_err(|e| ConfigError::InvalidToml { path: path.to_path_buf(), source: e }) +} + +// ✅ Tests: unwrap() is fine +#[test] +fn it_should_parse_valid_config() { + let config = Config::parse(VALID_TOML).unwrap(); + assert_eq!(config.http_api.bind_address, "127.0.0.1:1212"); +} +``` + +## Quick Checklist + +- [ ] Error type uses `thiserror::Error` derive +- [ ] Error message includes specific context (names, paths, addresses, values) +- [ ] Error message includes fix instructions where possible +- [ ] Prefer `enum` over `Box<dyn Error>` or `anyhow` in library code +- [ ] No vague messages like "invalid input" or "error occurred" +- [ ] No `.unwrap()` in production code (tests and doc examples are fine) +- [ ] Consider `located-error` for diagnostics-rich errors diff --git a/.github/skills/dev/rust-code-quality/handle-secrets/SKILL.md b/.github/skills/dev/rust-code-quality/handle-secrets/SKILL.md new file mode 100644 index 000000000..b3e6e5d43 --- /dev/null +++ b/.github/skills/dev/rust-code-quality/handle-secrets/SKILL.md @@ -0,0 +1,87 @@ +--- +name: handle-secrets +description: Guide for handling sensitive data (secrets) in this Rust project. NEVER use plain String for API tokens, passwords, or other credentials. Use the secrecy crate's Secret<T> wrapper to prevent accidental exposure through Debug output, logs, and error messages. Call .expose_secret() only when the actual value is needed. Use when working with credentials, API keys, tokens, passwords, or any sensitive configuration. Triggers on "secret", "API token", "password", "credential", "sensitive data", "secrecy", or "expose secret". +metadata: + author: torrust + version: "1.0" +--- + +# Handling Sensitive Data (Secrets) + +## Core Rule + +**NEVER use plain `String` for sensitive data.** Wrap secrets in `secrecy::Secret<String>` +(or similar) to prevent accidental exposure. + +```rust +// ❌ WRONG: secret leaked in Debug output +pub struct ApiConfig { + pub token: String, +} +println!("{config:?}"); // → ApiConfig { token: "secret_abc123" } — LEAKED! +``` + +```rust +// ✅ CORRECT: secret redacted in Debug +use secrecy::Secret; +pub struct ApiConfig { + pub token: Secret<String>, +} +println!("{config:?}"); // → ApiConfig { token: Secret([REDACTED]) } +``` + +## Using the `secrecy` Crate + +Add the dependency: + +```toml +[dependencies] +secrecy = { workspace = true } +``` + +Basic usage: + +```rust +use secrecy::{Secret, ExposeSecret}; + +// Wrap the secret +let token = Secret::new(String::from("my-api-token")); + +// Access the value only when truly needed (e.g., making the actual API call) +let token_str: &str = token.expose_secret(); +``` + +## What to Protect + +Wrap with `Secret<T>` when the value is: + +- API tokens (REST API admin token, external service tokens) +- Passwords (database credentials, service accounts) +- Private keys or certificates + +## Rules for `.expose_secret()` + +- Call **as late as possible** — only at the point where the value is required +- **Never** call in `log!`, `debug!`, `info!`, `warn!`, `error!` macros +- **Never** call in `Display` or `Debug` implementations +- **Never** include in error messages that may be logged or shown to users + +```rust +// ✅ Correct: called at last moment for HTTP header +let response = client + .get(url) + .header("Authorization", format!("Bearer {}", token.expose_secret())) + .send() + .await?; + +// ❌ Wrong: exposed in log +tracing::debug!("Using token: {}", token.expose_secret()); +``` + +## Checklist + +- [ ] No plain `String` fields for tokens, passwords, or private keys +- [ ] `Secret<String>` (or equivalent) used for all sensitive values +- [ ] `.expose_secret()` called only at the last moment +- [ ] No `.expose_secret()` in log statements or error messages +- [ ] No sensitive values in `Display` or `Debug` output diff --git a/.github/skills/dev/testing/write-unit-test/SKILL.md b/.github/skills/dev/testing/write-unit-test/SKILL.md new file mode 100644 index 000000000..3d4569bd5 --- /dev/null +++ b/.github/skills/dev/testing/write-unit-test/SKILL.md @@ -0,0 +1,201 @@ +.github/skills/dev/testing/write-unit-test/SKILL.md--- +name: write-unit-test +description: Guide for writing unit tests following project conventions including behavior-driven naming (it*should*\*), AAA pattern, MockClock for deterministic time testing, and parameterized tests with rstest. Use when adding tests for domain entities, value objects, utilities, or tracker logic. Triggers on "write unit test", "add test", "test coverage", "unit testing", or "add unit tests". +metadata: +author: torrust +version: "1.0" + +--- + +# Writing Unit Tests + +## Core Principles + +Unit tests in this project are written against the **Test Desiderata** — the 12 properties that +make tests valuable, defined by Kent Beck. Not every property applies equally to every test, but +treat them as the standard to reason about and optimize for. + +| Property | What it means | +| ------------------------- | ----------------------------------------------------------------------------------- | +| **Isolated** | Tests return the same result regardless of run order. No shared mutable state. | +| **Composable** | Different dimensions of variability can be tested separately and results combined. | +| **Deterministic** | Same inputs always produce the same result. No randomness, no wall-clock time. | +| **Fast** | Tests run in milliseconds. Unit tests must never block on I/O or sleep. | +| **Writable** | Writing the test should cost much less than writing the code it covers. | +| **Readable** | A reader can understand what behaviour is being tested and why, without context. | +| **Behavioral** | Tests are sensitive to changes in observable behaviour, not internal structure. | +| **Structure-insensitive** | Refactoring the implementation should not break tests that test the same behaviour. | +| **Automated** | Tests run without human intervention (`cargo test`). | +| **Specific** | When a test fails, the cause is immediately obvious from the failure message. | +| **Predictive** | Passing tests give genuine confidence the code is ready for production. | +| **Inspiring** | Passing the full suite inspires confidence to ship. | + +Some properties support each other (automation makes tests faster). Some trade off against each +other (more predictive tests tend to be slower). Use composability to resolve apparent conflicts. + +Reference: <https://testdesiderata.com/> and Kent Beck's original papers on +[Test Desiderata](https://medium.com/@kentbeck_7670/test-desiderata-94150638a4b3) and +[Programmer Test Principles](https://medium.com/@kentbeck_7670/programmer-test-principles-d01c064d7934). + +### Project-specific conventions + +- **Behavior-driven naming** — test names document what the code does +- **AAA Pattern** — Arrange → Act → Assert (clear structure) +- **Deterministic** — use `MockClock` instead of real time (see Phase 2) +- **Isolated** — no shared mutable state between tests +- **Fast** — unit tests run in milliseconds + +## Phase 1: Basic Unit Test + +### Naming Convention + +**Format**: `it_should_{expected_behavior}_when_{condition}` + +- Always use the `it_should_` prefix +- Never use the `test_` prefix +- Use `when_` or `given_` for conditions +- Be specific and descriptive + +```rust +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_should_return_error_when_info_hash_is_invalid() { + // Arrange + let invalid_hash = "not-a-valid-hash"; + + // Act + let result = InfoHash::from_str(invalid_hash); + + // Assert + assert!(result.is_err()); + } + + #[test] + fn it_should_parse_valid_info_hash() { + // Arrange + let valid_hex = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + // Act + let result = InfoHash::from_str(valid_hex); + + // Assert + assert!(result.is_ok()); + } +} +``` + +### Running Tests + +```bash +# Run all tests in a package +cargo test -p tracker-core + +# Run specific test by name +cargo test it_should_return_error_when_info_hash_is_invalid + +# Run tests in a module +cargo test info_hash::tests + +# Run with output +cargo test -- --nocapture +``` + +## Phase 2: Deterministic Time with MockClock + +The `clock` workspace package provides a `MockClock` for deterministic time testing. +Never use `std::time::SystemTime::now()` or `chrono::Utc::now()` directly in production code +that needs testing. + +### Inject the Clock Dependency + +```rust +use torrust_tracker_clock::clock::Clock; +use std::sync::Arc; + +pub struct PeerList { + clock: Arc<dyn Clock>, +} + +impl PeerList { + pub fn new(clock: Arc<dyn Clock>) -> Self { + Self { clock } + } + + pub fn is_peer_expired(&self, last_seen: i64, ttl: u32) -> bool { + let now = self.clock.now(); + now - last_seen > i64::from(ttl) + } +} +``` + +### Use MockClock in Tests + +```rust +#[cfg(test)] +mod tests { + use super::*; + use torrust_tracker_clock::clock::stopped::Stopped as MockClock; + use std::sync::Arc; + + #[test] + fn it_should_mark_peer_as_expired_when_ttl_has_elapsed() { + // Arrange + let fixed_time = 1_700_000_100i64; // specific Unix timestamp + let clock = Arc::new(MockClock::new(fixed_time)); + let list = PeerList::new(clock); + let last_seen = 1_700_000_000i64; + let ttl = 60u32; + + // Act + let expired = list.is_peer_expired(last_seen, ttl); + + // Assert + assert!(expired); + } +} +``` + +## Phase 3: Parameterized Tests with rstest + +Use `rstest` for multiple input/output combinations to avoid repetition. + +```toml +[dev-dependencies] +rstest = { workspace = true } +``` + +```rust +use rstest::rstest; + +#[rstest] +#[case("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true)] +#[case("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", true)] +#[case("not-a-hash", false)] +#[case("", false)] +fn it_should_validate_info_hash(#[case] input: &str, #[case] is_valid: bool) { + let result = InfoHash::from_str(input); + assert_eq!(result.is_ok(), is_valid, "input: {input}"); +} +``` + +## Phase 4: Test Helpers + +The `test-helpers` workspace package provides shared test utilities. + +```toml +[dev-dependencies] +torrust-tracker-test-helpers = { workspace = true } +``` + +Check the package for available mock servers, fixture generators, and utility types. + +## Quick Checklist + +- [ ] Test name uses `it_should_` prefix +- [ ] Test follows AAA pattern with comments (`// Arrange`, `// Act`, `// Assert`) +- [ ] No `std::time::SystemTime::now()` in production code — inject `Clock` instead +- [ ] No shared mutable state between tests +- [ ] `cargo test -p <package>` passes diff --git a/docs/adrs/README.md b/docs/adrs/README.md index 85986fc36..5fd40aa24 100644 --- a/docs/adrs/README.md +++ b/docs/adrs/README.md @@ -1,23 +1,32 @@ # Architectural Decision Records (ADRs) -This directory contains the architectural decision records (ADRs) for the -project. ADRs are a way to document the architectural decisions made in the -project. +This directory contains the architectural decision records (ADRs) for the project. +ADRs document architectural decisions — what was decided, why, and what alternatives +were considered. More info: <https://adr.github.io/>. -## How to add a new record +See [index.md](index.md) for the full list of ADRs. -For the prefix: +## How to Add a New ADR -```s +Generate the timestamp prefix (UTC): + +```shell date -u +"%Y%m%d%H%M%S" ``` -Then you can create a new markdown file with the following format: +Create a new Markdown file using the format `YYYYMMDDHHMMSS_snake_case_title.md`: -```s +```shell 20230510152112_title.md ``` -For the time being, we are not following any specific template. +Then add a row to the [Index](index.md) table. + +There is no rigid template. A typical ADR includes: + +- **Description** — the problem or context motivating the decision +- **Agreement** — what was decided and why +- **Date** — decision date (`YYYY-MM-DD`) +- **References** — related issues, PRs, external docs diff --git a/docs/adrs/index.md b/docs/adrs/index.md new file mode 100644 index 000000000..8a9e64cb9 --- /dev/null +++ b/docs/adrs/index.md @@ -0,0 +1,5 @@ +# ADR Index + +| ADR | Date | Title | Short Description | +| --------------------------------------------------------------------------------- | ---------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| [20240227164834](20240227164834_use_plural_for_modules_containing_collections.md) | 2024-02-27 | Use plural for modules containing collections | Module names should use plural when they contain multiple types with the same responsibility (e.g. `requests/`, `responses/`). | diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index b482e1f23..3900e3b18 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -103,13 +103,13 @@ Checkpoint: Define reusable, project-specific skills that agents can load to perform specialized tasks on this repository consistently. -- [ ] Create `.github/skills/` directory -- [ ] Review and confirm the candidate skills listed below (add, remove, or adjust before starting implementation) -- [ ] For each skill, create a directory with: +- [x] Create `.github/skills/` directory +- [x] Review and confirm the candidate skills listed below (add, remove, or adjust before starting implementation) +- [x] For each skill, create a directory with: - `SKILL.md` — YAML frontmatter (`name`, `description`, optional `license`, `compatibility`) + step-by-step instructions - `scripts/` (optional) — executable scripts the agent can run - `references/` (optional) — additional reference documentation -- [ ] Validate skill files against the Agent Skills spec (name rules: lowercase, hyphens, no consecutive hyphens, max 64 chars; description: max 1024 chars) +- [x] Validate skill files against the Agent Skills spec (name rules: lowercase, hyphens, no consecutive hyphens, max 64 chars; description: max 1024 chars) **Candidate initial skills** (ported / adapted from `torrust-tracker-deployer`): @@ -131,37 +131,39 @@ Directory layout to mirror the deployer structure: testing/ ``` -**`add-new-skill`** — meta-skill: guide for creating new Agent Skills for this repository. +**`add-new-skill`** ✅ — meta-skill: guide for creating new Agent Skills for this repository. **`dev/git-workflow/`**: -- `commit-changes` — commit following Conventional Commits; pre-commit verification checklist. -- `create-feature-branch` — branch naming convention and lifecycle. -- `open-pull-request` — open a PR via GitHub CLI or GitHub MCP tool; pre-flight checks. -- `release-new-version` — version bump, signed release commit, signed tag, CI verification. -- `review-pr` — review a PR against Torrust quality standards and checklist. -- `run-linters` — run the full linting suite (`linter all`); fix individual linter failures. -- `run-pre-commit-checks` — mandatory quality gates before every commit. +- `commit-changes` ✅ — commit following Conventional Commits; pre-commit verification checklist. +- `create-feature-branch` ✅ — branch naming convention and lifecycle. +- `open-pull-request` ✅ — open a PR via GitHub CLI or GitHub MCP tool; pre-flight checks. +- `release-new-version` ✅ — version bump, signed release commit, signed tag, CI verification. +- `review-pr` ✅ — review a PR against Torrust quality standards and checklist. +- `run-linters` ✅ — run the full linting suite (`linter all`); fix individual linter failures. +- `run-pre-commit-checks` ✅ — mandatory quality gates before every commit. **`dev/maintenance/`**: -- `update-dependencies` — run `cargo update`, create branch, commit, push, open PR. +- `install-linter` ✅ — install the `linter` binary and its external tool dependencies. +- `setup-dev-environment` ✅ — full onboarding guide: system deps, Rust toolchain, storage dirs, linter, git hooks, smoke test. +- `update-dependencies` ✅ — run `cargo update`, create branch, commit, push, open PR. **`dev/planning/`**: -- `create-adr` — create an Architectural Decision Record in `docs/adrs/`. -- `create-issue` — draft and open a GitHub issue following project conventions. -- `write-markdown-docs` — GFM pitfalls (auto-links, ordered list numbering, etc.). -- `cleanup-completed-issues` — remove issue doc files and update roadmap after PR merge. +- `create-adr` ✅ — create an Architectural Decision Record in `docs/adrs/`. +- `create-issue` ✅ — draft and open a GitHub issue following project conventions. +- `write-markdown-docs` ✅ — GFM pitfalls (auto-links, ordered list numbering, etc.). +- `cleanup-completed-issues` ✅ — remove issue doc files and update roadmap after PR merge. **`dev/rust-code-quality/`**: -- `handle-errors-in-code` — `thiserror`-based structured errors; what/where/when/why context. -- `handle-secrets` — wrapper types for tokens/passwords; never use plain `String` for secrets. +- `handle-errors-in-code` ✅ — `thiserror`-based structured errors; what/where/when/why context. +- `handle-secrets` ✅ — wrapper types for tokens/passwords; never use plain `String` for secrets. **`dev/testing/`**: -- `write-unit-test` — `it_should_*` naming, AAA pattern, `MockClock`, `TempDir`, `rstest`. +- `write-unit-test` ✅ — `it_should_*` naming, AAA pattern, `MockClock`, `TempDir`, `rstest`. Commit message: `docs(agents): add initial agent skills under .github/skills/` diff --git a/docs/templates/ADR.md b/docs/templates/ADR.md new file mode 100644 index 000000000..fa8aebe27 --- /dev/null +++ b/docs/templates/ADR.md @@ -0,0 +1,24 @@ +# [Title] + +## Description + +What is the issue motivating this decision? Provide enough context for future +readers who have no prior background. + +## Agreement + +What was decided and why? Be concrete. Include code examples if the decision +involves specific patterns. + +Optional sub-sections: + +- **Alternatives Considered** — other options explored and why they were rejected +- **Consequences** — positive and negative effects of the decision + +## Date + +YYYY-MM-DD + +## References + +Links to related issues, PRs, ADRs, and external documentation. diff --git a/docs/templates/ISSUE.md b/docs/templates/ISSUE.md new file mode 100644 index 000000000..7c899bacd --- /dev/null +++ b/docs/templates/ISSUE.md @@ -0,0 +1,33 @@ +# Issue: {Title} + +## Overview + +Clear description of what needs to be done and why. + +## Goals + +- [ ] Goal 1 +- [ ] Goal 2 + +## Implementation Plan + +### Task 1: {Task Title} + +- [ ] Sub-task a +- [ ] Sub-task b + +### Task 2: {Task Title} + +- [ ] Sub-task a +- [ ] Sub-task b + +## Acceptance Criteria + +- [ ] All tests pass +- [ ] `linter all` exits with code `0` +- [ ] Documentation updated + +## References + +- Related issues: #{number} +- Related ADRs: `docs/adrs/...` diff --git a/project-words.txt b/project-words.txt index ce81bfea6..627b54f09 100644 --- a/project-words.txt +++ b/project-words.txt @@ -7,13 +7,16 @@ ASMS asyn autoclean AUTOINCREMENT +autolinks automock Avicora Azureus +backlinks bdecode bencode bencoded bencoding +behaviour beps binascii binstall @@ -184,6 +187,7 @@ underflows Unsendable untuple uroot +usize Vagaa valgrind Vitaly @@ -239,6 +243,7 @@ sysmalloc sysret timespec toki +toplevel torru ttwu uninit diff --git a/scripts/install-git-hooks.sh b/scripts/install-git-hooks.sh new file mode 100755 index 000000000..8762bc88c --- /dev/null +++ b/scripts/install-git-hooks.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Install project Git hooks from .githooks/ into .git/hooks/. +# +# Usage: +# ./scripts/install-git-hooks.sh +# +# Run once after cloning the repository. Re-run to update hooks after +# they change. + +set -euo pipefail + +REPO_ROOT="$(git rev-parse --show-toplevel)" +HOOKS_SRC="${REPO_ROOT}/.githooks" +HOOKS_DST="${REPO_ROOT}/.git/hooks" + +if [ ! -d "${HOOKS_SRC}" ]; then + echo "ERROR: .githooks/ directory not found at ${HOOKS_SRC}" + exit 1 +fi + +installed=0 + +for hook in "${HOOKS_SRC}"/*; do + hook_name="$(basename "${hook}")" + dest="${HOOKS_DST}/${hook_name}" + + cp "${hook}" "${dest}" + chmod +x "${dest}" + + echo "Installed: ${hook_name} → .git/hooks/${hook_name}" + installed=$((installed + 1)) +done + +echo "" +echo "==========================================" +echo "SUCCESS: ${installed} hook(s) installed." +echo "==========================================" diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh new file mode 100755 index 000000000..04dec26f4 --- /dev/null +++ b/scripts/pre-commit.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# Pre-commit verification script +# Run all mandatory checks before committing changes. +# +# Usage: +# ./scripts/pre-commit.sh +# +# Expected runtime: ~3 minutes on a modern developer machine. +# AI agents: set a per-command timeout of at least 5 minutes before invoking this script. +# +# All steps must pass (exit 0) before committing. + +set -euo pipefail + +# ============================================================================ +# STEPS +# ============================================================================ +# Each step: "description|success_message|command" + +declare -a STEPS=( + "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete" + "Running all linters|All linters passed|linter all" + "Running documentation tests|Documentation tests passed|cargo test --doc --workspace" + "Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features" +) + +# ============================================================================ +# HELPER FUNCTIONS +# ============================================================================ + +format_time() { + local total_seconds=$1 + local minutes=$((total_seconds / 60)) + local seconds=$((total_seconds % 60)) + if [ "$minutes" -gt 0 ]; then + echo "${minutes}m ${seconds}s" + else + echo "${seconds}s" + fi +} + +run_step() { + local step_number=$1 + local total_steps=$2 + local description=$3 + local success_message=$4 + local command=$5 + + echo "[Step ${step_number}/${total_steps}] ${description}..." + + local step_start=$SECONDS + eval "${command}" + local step_elapsed=$((SECONDS - step_start)) + + echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))" + echo +} + +trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-commit checks failed!"; echo "Fix the errors above before committing."; echo "=========================================="; exit 1' ERR + +# ============================================================================ +# MAIN +# ============================================================================ + +TOTAL_START=$SECONDS +TOTAL_STEPS=${#STEPS[@]} + +echo "Running pre-commit checks..." +echo + +for i in "${!STEPS[@]}"; do + IFS='|' read -r description success_message command <<< "${STEPS[$i]}" + run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}" +done + +TOTAL_ELAPSED=$((SECONDS - TOTAL_START)) +echo "==========================================" +echo "SUCCESS: All pre-commit checks passed! ($(format_time "${TOTAL_ELAPSED}"))" +echo "==========================================" +echo +echo "You can now safely stage and commit your changes." From 60dc5f5a614769294818af741ff34be9db394229 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Mon, 20 Apr 2026 20:09:52 +0100 Subject: [PATCH 64/79] feat(agents): add custom agents for committer, implementer, and complexity auditor (#1697) - Add .github/agents/committer.agent.md: commit specialist with GPG signing - Add .github/agents/implementer.agent.md: TDD implementer with sub-agent delegation - Add .github/agents/complexity-auditor.agent.md: cyclomatic/cognitive complexity checker - Update project-words.txt: add cyclomatic, analyse, penalise - Update docs/issues/1697-ai-agent-configuration.md: mark Tasks 3 and 4 complete --- .github/agents/committer.agent.md | 53 +++++++++++++ .github/agents/complexity-auditor.agent.md | 86 ++++++++++++++++++++++ .github/agents/implementer.agent.md | 86 ++++++++++++++++++++++ docs/issues/1697-ai-agent-configuration.md | 39 +++++++--- project-words.txt | 3 + 5 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 .github/agents/committer.agent.md create mode 100644 .github/agents/complexity-auditor.agent.md create mode 100644 .github/agents/implementer.agent.md diff --git a/.github/agents/committer.agent.md b/.github/agents/committer.agent.md new file mode 100644 index 000000000..016ee2c0f --- /dev/null +++ b/.github/agents/committer.agent.md @@ -0,0 +1,53 @@ +--- +name: Committer +description: Proactive commit specialist for this repository. Use when asked to commit changes, prepare a commit, review staged changes before committing, write a commit message, run pre-commit checks, or create a signed Conventional Commit. +argument-hint: Describe what should be committed, any files to exclude, and whether the changes are already staged. +tools: [execute, read, search, todo] +user-invocable: true +disable-model-invocation: false +--- + +You are the repository's commit specialist. Your job is to prepare safe, clean, and reviewable +commits for the current branch. + +Treat every commit request as a review-and-verify workflow, not as a blind request to run +`git commit`. + +## Repository Rules + +- Follow `AGENTS.md` for repository-wide behaviour and + `.github/skills/dev/git-workflow/commit-changes/SKILL.md` for commit-specific reference details. +- The pre-commit validation command is `./scripts/pre-commit.sh`. +- Create GPG-signed Conventional Commits (`git commit -S`). + +## Required Workflow + +1. Read the current branch, `git status`, and the staged or unstaged diff relevant to the request. +2. Summarize the intended commit scope before taking action. +3. Ensure the commit scope is coherent and does not accidentally mix unrelated changes. +4. Run `./scripts/pre-commit.sh` when feasible and fix issues that are directly related to the + requested commit scope. +5. Propose a precise Conventional Commit message. +6. Create the commit with `git commit -S` only after the scope is clear and blockers are resolved. +7. After committing, run a quick verification check and report the resulting commit summary. + +## Constraints + +- Do not write code. +- Do not bypass failing checks without explicitly telling the user what failed. +- Do not rewrite or revert unrelated user changes. +- Do not create empty, vague, or non-conventional commit messages. +- Do not commit secrets, backup junk, or accidental files. +- Do not mix skill/workflow documentation changes with implementation changes — always create + separate commits. + +## Output Format + +When handling a commit task, respond in this order: + +1. Commit scope summary +2. Blockers, anomalies, or risks +3. Checks run and results +4. Proposed commit message +5. Commit status +6. Post-commit verification diff --git a/.github/agents/complexity-auditor.agent.md b/.github/agents/complexity-auditor.agent.md new file mode 100644 index 000000000..91ae2a085 --- /dev/null +++ b/.github/agents/complexity-auditor.agent.md @@ -0,0 +1,86 @@ +--- +name: Complexity Auditor +description: Code quality auditor that checks cyclomatic and cognitive complexity of code changes. Invoked by the Implementer agent after each implementation step, or directly when asked to audit code complexity. Reports PASS, WARN, or FAIL for each changed function. +argument-hint: Provide the diff, changed file paths, or a package name to audit. +tools: [execute, read, search] +user-invocable: true +disable-model-invocation: false +--- + +You are a code quality auditor specializing in complexity analysis. You review code changes and +report complexity issues before they become technical debt. + +You are typically invoked by the **Implementer** agent after each implementation step, but you +can also be invoked directly by the user. + +## Audit Scope + +Focus on the diff introduced by the current task. Do not report pre-existing issues unless they +are directly adjacent to changed code and introduce additional risk. + +## Complexity Checks + +### 1. Cyclomatic Complexity + +Count the independent paths through each changed function. Each of the following adds one branch: +`if`, `else if`, `match` arm, `while`, `for`, `loop`, `?` early return, and `&&`/`||` in a +condition. A function starts at complexity 1. + +| Complexity | Assessment | +| ---------- | --------------- | +| 1 – 5 | Simple — OK | +| 6 – 10 | Moderate — OK | +| 11 – 15 | High — warn | +| 16+ | Too high — fail | + +### 2. Cognitive Complexity (via Clippy) + +Run the following to surface Clippy cognitive complexity warnings: + +```bash +cargo clippy --package <affected-package> -- \ + -W clippy::cognitive_complexity \ + -D warnings +``` + +Any `cognitive_complexity` warning from Clippy is a failing issue. + +### 3. Nesting Depth + +Flag functions with more than 3 levels of nesting. Deep nesting hides intent and makes +reasoning difficult. + +### 4. Function Length + +Flag functions longer than 50 lines. Long functions are a proxy for missing decomposition. + +## Audit Workflow + +1. Identify all functions added or changed in the current diff. +2. For each function, compute cyclomatic complexity from the source. +3. Run `cargo clippy` with the cognitive complexity lint enabled. +4. Check nesting depth and function length. +5. Report findings using the output format below. + +## Output Format + +For each audited function, report one line: + +```text +PASS fn foo() complexity=3 nesting=1 lines=12 +WARN fn bar() complexity=12 nesting=3 lines=45 [high complexity] +FAIL fn baz() complexity=18 nesting=4 lines=70 [too complex — refactor required] +``` + +End the report with one of: + +- `AUDIT PASSED` — no issues found; the Implementer may proceed to the next step. +- `AUDIT WARNED` — non-blocking issues found; describe each concern briefly. +- `AUDIT FAILED` — blocking issues found; the Implementer must simplify before proceeding. + +## Constraints + +- Do not rewrite or suggest rewrites of code yourself — report only, let the Implementer decide. +- Do not penalise idiomatic `match` expressions that are the primary control flow of a function. +- Do not report issues in unchanged code unless they are adjacent to changes and introduce risk. +- Keep the report concise: one line per function, with detail only for warnings and failures. diff --git a/.github/agents/implementer.agent.md b/.github/agents/implementer.agent.md new file mode 100644 index 000000000..a083a507c --- /dev/null +++ b/.github/agents/implementer.agent.md @@ -0,0 +1,86 @@ +--- +name: Implementer +description: Software implementer that applies Test-Driven Development and seeks simple solutions. Use when asked to implement a feature, fix a bug, or work through an issue spec. Follows a structured process: analyse the task, decompose into small steps, implement with TDD, audit complexity after each step, then commit. +argument-hint: Describe the task or link the issue spec document. Clarify any constraints or acceptance criteria. +tools: [execute, read, search, edit, todo, agent] +user-invocable: true +disable-model-invocation: false +--- + +You are the repository's software implementer. Your job is to implement tasks correctly, simply, +and verifiably. + +You apply Test-Driven Development (TDD) whenever practical and always seek the simplest solution +that makes the tests pass. + +## Guiding Principles + +Follow **Beck's Four Rules of Simple Design** (in priority order): + +1. **Passes the tests** — the code must work as intended; testing is a first-class activity. +2. **Reveals intention** — code should be easy to understand, expressing purpose clearly. +3. **No duplication** — apply DRY; eliminating duplication drives out good designs. +4. **Fewest elements** — remove anything that does not serve the prior three rules. + +Reference: [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.html) + +## Repository Rules + +- Follow `AGENTS.md` for repository-wide conventions. +- The pre-commit validation command is `./scripts/pre-commit.sh`. +- Relevant skills to load when needed: + - `.github/skills/dev/testing/write-unit-test/SKILL.md` — test naming and Arrange/Act/Assert pattern. + - `.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md` — error handling. + - `.github/skills/dev/git-workflow/commit-changes/SKILL.md` — commit conventions. + +## Required Workflow + +### Step 1 — Analyse the Task + +Before writing any code: + +1. Read `AGENTS.md` and any relevant skill files for the area being changed. +2. Read the issue spec or task description in full. +3. Identify the scope: what must change and what must not change. +4. Ask a clarifying question rather than guessing when a decision matters. + +### Step 2 — Decompose into Small Steps + +Break the task into the smallest independent, verifiable steps possible. Use the todo list to +track progress. Each step should: + +- Have a single, clear intent. +- Be verifiable by a test or observable behaviour. +- Be committable independently when complete. + +### Step 3 — Implement Each Step (TDD Preferred) + +For each step: + +1. **Write a failing test first** (red) — express the expected behaviour in a test. +2. **Write minimal production code** to make the test pass (green). +3. **Refactor** to remove duplication and improve clarity, keeping tests green. +4. Verify with `cargo test -p <package>` before moving on. + +When TDD is not practical (e.g. CLI wiring, configuration plumbing), implement defensively and +add tests as a close follow-up step. + +### Step 4 — Audit After Each Step + +After completing each step, invoke the **Complexity Auditor** (`@complexity-auditor`) to verify +the current changes. Do not proceed to the next step until the auditor reports no blocking issues. + +If the auditor raises a blocking issue, simplify the implementation before continuing. + +### Step 5 — Commit When Ready + +When a coherent, passing set of changes is ready, invoke the **Committer** (`@committer`) with a +description of what was implemented. Do not commit directly — always delegate to the Committer. + +## Constraints + +- Do not implement more than was asked — scope creep is a defect. +- Do not suppress compiler warnings or clippy lints without a documented reason. +- Do not add dependencies without running `cargo machete` afterward. +- Do not commit code that fails `./scripts/pre-commit.sh`. +- Do not skip the audit step, even for small changes. diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index 3900e3b18..1e9399ad7 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -187,22 +187,36 @@ Checkpoint: Define custom GitHub Copilot agents tailored to Torrust project workflows so that specialized tasks can be delegated to focused agents with the right prompt context. -- [ ] Create `.github/agents/` directory -- [ ] Identify workflows that benefit from a dedicated agent (e.g. issue implementation planner, code reviewer, documentation writer, release drafter) -- [ ] For each agent, create `.github/agents/<agent-name>.md` with: +- [x] Create `.github/agents/` directory +- [x] Identify workflows that benefit from a dedicated agent +- [x] For each agent, create `.github/agents/<agent-name>.md` with: - YAML frontmatter: `name` (optional), `description`, optional `tools` - Prompt body: role definition, scope, constraints, and step-by-step instructions - [ ] Test each custom agent by assigning it to a task or issue in GitHub Copilot CLI **Candidate initial agents**: -- `committer` — commit specialist: reads branch/diff, runs pre-commit checks (`linter all`), - proposes a GPG-signed Conventional Commit message, and creates the commit only after scope and - checks are clear. Reference: +- `committer` ✅ — commit specialist: reads branch/diff, runs pre-commit checks + (`./scripts/pre-commit.sh`), proposes a GPG-signed Conventional Commit message, and creates + the commit only after scope and checks are clear. Reference: [`torrust-tracker-demo/.github/agents/commiter.agent.md`](https://raw.githubusercontent.com/torrust/torrust-tracker-demo/refs/heads/main/.github/agents/commiter.agent.md) -- `issue-planner` — given a GitHub issue, produces a detailed implementation plan document (like the ones in `docs/issues/`) including branch name, task breakdown, checkpoints, and commit message suggestions -- `code-reviewer` — reviews PRs against Torrust coding conventions, clippy rules, and security considerations -- `docs-writer` — creates or updates documentation files following the existing docs structure +- `implementer` ✅ — software implementer that applies Test-Driven Development and seeks the + simplest solution. Follows a structured process: analyse → decompose into small steps → + implement with TDD → call the Complexity Auditor after each step → call the Committer when + ready. Guided by Beck's Four Rules of Simple Design. +- `complexity-auditor` ✅ — code quality auditor that checks cyclomatic and cognitive complexity + of changes after each implementation step. Reports PASS/WARN/FAIL per function using thresholds + and Clippy's `cognitive_complexity` lint. Called by the Implementer; can also be invoked + directly. + +**Future agents** (not yet implemented): + +- `issue-planner` — given a GitHub issue, produces a detailed implementation plan document + (like those in `docs/issues/`) including branch name, task breakdown, checkpoints, and commit + message suggestions. +- `code-reviewer` — reviews PRs against Torrust coding conventions, clippy rules, and security + considerations. +- `docs-writer` — creates or updates documentation files following the existing docs structure. Commit message: `docs(agents): add initial custom agents under .github/agents/` @@ -225,6 +239,13 @@ Once the root file is stable, evaluate whether any workspace packages have suffi conventions or setup to warrant their own `AGENTS.md`. This can be tracked as a separate follow-up issue. +- [x] Evaluate workspace packages for package-specific conventions +- [x] Add `packages/AGENTS.md` — guidance scoped to all workspace packages +- [x] Add `src/AGENTS.md` — guidance scoped to the main binary/library source + +> **Note**: Completed as part of Task 1. `packages/AGENTS.md` and `src/AGENTS.md` were added +> alongside the root `AGENTS.md`. + --- ### Task 5: Add `copilot-setup-steps.yml` workflow diff --git a/project-words.txt b/project-words.txt index 627b54f09..00939a1ba 100644 --- a/project-words.txt +++ b/project-words.txt @@ -1,6 +1,7 @@ Addrs adduser alekitto +analyse appuser Arvid ASMS @@ -47,6 +48,7 @@ Containerfile conv curr cvar +cyclomatic Cyberneering dashmap datagram @@ -125,6 +127,7 @@ obra oneshot ostr Pando +penalise peekable peerlist programatik From 36908d8982e14ece0c65c2067f6944d707058d04 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Mon, 20 Apr 2026 20:59:25 +0100 Subject: [PATCH 65/79] ci(copilot): add copilot-setup-steps workflow (#1697) - Add .github/workflows/copilot-setup-steps.yml: prepares Copilot cloud agent environment before it starts working on any task - Triggers on workflow_dispatch, push and pull_request (scoped to file) - Steps: checkout (v6), stable Rust toolchain, rust-cache, cargo build, install linter, install cargo-machete, install git hooks, linter all - Update docs/issues/1697-ai-agent-configuration.md: mark Task 5 complete --- .github/workflows/copilot-setup-steps.yml | 49 ++++++++++++++++++++++ docs/issues/1697-ai-agent-configuration.md | 19 +++++---- 2 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/copilot-setup-steps.yml diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..141cf8df4 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,49 @@ +name: "Copilot Setup Steps" + +# Automatically run the setup steps when they are changed to allow for easy +# validation, and allow manual testing through the repository's "Actions" tab. +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # The job MUST be called `copilot-setup-steps` or it will not be picked up + # by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + timeout-minutes: 30 + + # Set the permissions to the lowest permissions possible needed for your + # steps. Copilot will be given its own token for its operations. + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Enable Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Build workspace + run: cargo build --workspace + + - name: Install linter + run: cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter + + - name: Install cargo-machete + run: cargo install cargo-machete + + - name: Install Git pre-commit hooks + run: ./scripts/install-git-hooks.sh + + - name: Smoke-check — run all linters + run: linter all diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index 1e9399ad7..eb01b32a9 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -264,19 +264,20 @@ https://raw.githubusercontent.com/torrust/torrust-tracker-deployer/refs/heads/ma Minimum steps to include: -- [ ] Trigger on `workflow_dispatch`, `push` and `pull_request` (scoped to the workflow file path) -- [ ] `copilot-setup-steps` job on `ubuntu-latest`, `timeout-minutes: 30`, `permissions: contents: read` -- [ ] `actions/checkout@v5` — check out the repository (verify this is still the latest stable +- [x] Trigger on `workflow_dispatch`, `push` and `pull_request` (scoped to the workflow file path) +- [x] `copilot-setup-steps` job on `ubuntu-latest`, `timeout-minutes: 30`, `permissions: contents: read` +- [x] `actions/checkout@v6` — check out the repository (verify this is still the latest stable version on the GitHub Marketplace before merging) -- [ ] `dtolnay/rust-toolchain@stable` — install the stable Rust toolchain (pin MSRV if needed) -- [ ] `Swatinem/rust-cache@v2` — cache `target/` and `~/.cargo` between runs -- [ ] `cargo build` warm-up — build the workspace (or key packages) so incremental compilation is +- [x] `dtolnay/rust-toolchain@stable` — install the stable Rust toolchain (pin MSRV if needed) +- [x] `Swatinem/rust-cache@v2` — cache `target/` and `~/.cargo` between runs +- [x] `cargo build` warm-up — build the workspace (or key packages) so incremental compilation is ready when Copilot starts editing -- [ ] Install the `linter` binary — +- [x] Install the `linter` binary — `cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter` -- [ ] Install `cargo-machete` — `cargo install cargo-machete`; ensures Copilot can run unused +- [x] Install `cargo-machete` — `cargo install cargo-machete`; ensures Copilot can run unused dependency checks (`cargo machete`) as required by the essential rules -- [ ] Smoke-check: run `linter all` to confirm the environment is healthy before Copilot begins +- [x] Smoke-check: run `linter all` to confirm the environment is healthy before Copilot begins +- [x] Install Git pre-commit hooks — `./scripts/install-git-hooks.sh` Commit message: `ci(copilot): add copilot-setup-steps workflow` From f35cd746683054f1ef89d2822e43c8f49195621f Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Mon, 20 Apr 2026 21:02:33 +0100 Subject: [PATCH 66/79] docs(adrs): add ADR for AI agent framework approach (#1697) - Add docs/adrs/20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md: records the decision to build a custom GitHub-Copilot-aligned agent framework (AGENTS.md + Agent Skills + Custom Agents) over third-party alternatives (obra/superpowers, gsd-build/get-shit-done) - Update docs/adrs/index.md: add new ADR entry - Update project-words.txt: add specialised - Update docs/issues/1697-ai-agent-configuration.md: mark Task 6 complete --- ..._github_copilot_aligned_agent_framework.md | 86 +++++++++++++++++++ docs/adrs/index.md | 7 +- docs/issues/1697-ai-agent-configuration.md | 4 +- project-words.txt | 1 + 4 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 docs/adrs/20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md diff --git a/docs/adrs/20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md b/docs/adrs/20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md new file mode 100644 index 000000000..556e131fb --- /dev/null +++ b/docs/adrs/20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md @@ -0,0 +1,86 @@ +# Adopt a Custom, GitHub-Copilot-Aligned Agent Framework + +## Description + +As AI coding agents become a more common part of the development workflow, the project needs a +clear strategy for how agents should interact with the codebase. Several third-party "agent +frameworks" exist that promise to give agents structure and purpose, but they each come with +trade-offs that may not fit the tracker's needs. + +This ADR records the decision to build a lightweight, first-party agent framework using the +open standards that GitHub Copilot already supports natively: `AGENTS.md`, Agent Skills, and +Custom Agent profiles. + +## Agreement + +We adopt a custom, GitHub-Copilot-aligned agent framework consisting of: + +- **`AGENTS.md`** at the repository root (and in key subdirectories) — following the + [agents.md](https://agents.md/) open standard stewarded by the Agentic AI Foundation under the + Linux Foundation. Provides AI coding agents with project context, build steps, test commands, + conventions, and essential rules. +- **Agent Skills** under `.github/skills/` — following the + [Agent Skills specification](https://agentskills.io/specification). Each skill is a directory + containing a `SKILL.md` file with YAML frontmatter and Markdown instructions, covering + repeatable tasks such as committing changes, running linters, creating ADRs, or setting up the + development environment. +- **Custom Agent profiles** under `.github/agents/` — Markdown files with YAML frontmatter + defining specialised Copilot agents (e.g. `committer`, `implementer`, `complexity-auditor`) + that can be invoked directly or as subagents. +- **`copilot-setup-steps.yml`** workflow — prepares the GitHub Copilot cloud agent environment + before it starts working on any task. + +### Alternatives Considered + +**[obra/superpowers](https://github.com/obra/superpowers)** + +A framework that adds "superpowers" to coding agents through a set of conventions and tools. +Not adopted for the following reasons: + +1. **Complexity mismatch** — introduces abstractions heavier than what tracker development needs. +1. **Precision requirements** — the tracker involves low-level Rust programming where agent work + must be reviewed carefully; generic productivity frameworks are not designed for that + constraint. +1. **Tooling churn risk** — depending on a third-party framework risks forced refactoring if + that framework is deprecated or pivots. + +**[gsd-build/get-shit-done](https://github.com/gsd-build/get-shit-done)** + +A productivity-oriented agent framework with opinionated workflows. +Not adopted for the same reasons as above, plus: + +1. **GitHub-first ecosystem** — the tracker is hosted on GitHub and makes intensive use of + GitHub resources (Actions, Copilot, MCP tools). Staying aligned with GitHub Copilot avoids + unnecessary integration friction. + +### Why the Custom Approach + +1. **Tailored fit** — shaped precisely to Torrust conventions, commit style, linting gates, and + package structure from day one. +1. **Proven in practice** — the same approach has already been validated during the development + of `torrust-tracker-deployer`. +1. **Agent-agnostic by design** — expressed as plain Markdown files (`AGENTS.md`, `SKILL.md`, + agent profiles), decoupled from any single agent product. Migration or multi-agent use is + straightforward. +1. **Incremental adoption** — individual skills, custom agents, or patterns from evaluated + frameworks can still be cherry-picked and integrated progressively if specific value is + identified. +1. **Stability** — a first-party approach is more stable than depending on a third-party + framework whose roadmap we do not control. + +## Date + +2026-04-20 + +## References + +- Issue: https://github.com/torrust/torrust-tracker/issues/1697 +- PR: https://github.com/torrust/torrust-tracker/pull/1699 +- AGENTS.md specification: https://agents.md/ +- Agent Skills specification: https://agentskills.io/specification +- GitHub Copilot — About agent skills: https://docs.github.com/en/copilot/concepts/agents/about-agent-skills +- GitHub Copilot — About custom agents: https://docs.github.com/en/copilot/concepts/agents/copilot-cli/about-custom-agents +- Customize the Copilot cloud agent environment: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/customize-the-agent-environment +- obra/superpowers: https://github.com/obra/superpowers +- gsd-build/get-shit-done: https://github.com/gsd-build/get-shit-done +- torrust-tracker-deployer (validated reference implementation): https://github.com/torrust/torrust-tracker-deployer diff --git a/docs/adrs/index.md b/docs/adrs/index.md index 8a9e64cb9..b6063e3ff 100644 --- a/docs/adrs/index.md +++ b/docs/adrs/index.md @@ -1,5 +1,6 @@ # ADR Index -| ADR | Date | Title | Short Description | -| --------------------------------------------------------------------------------- | ---------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -| [20240227164834](20240227164834_use_plural_for_modules_containing_collections.md) | 2024-02-27 | Use plural for modules containing collections | Module names should use plural when they contain multiple types with the same responsibility (e.g. `requests/`, `responses/`). | +| ADR | Date | Title | Short Description | +| --------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| [20240227164834](20240227164834_use_plural_for_modules_containing_collections.md) | 2024-02-27 | Use plural for modules containing collections | Module names should use plural when they contain multiple types with the same responsibility (e.g. `requests/`, `responses/`). | +| [20260420200013](20260420200013_adopt_custom_github_copilot_aligned_agent_framework.md) | 2026-04-20 | Adopt a custom, GitHub-Copilot-aligned agent framework | Use AGENTS.md, Agent Skills, and Custom Agent profiles instead of third-party agent frameworks. | diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index eb01b32a9..de84fb175 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -331,8 +331,8 @@ frameworks that were evaluated. 8. Incremental adoption — individual skills, custom agents, or patterns from those frameworks can still be cherry-picked and integrated progressively if specific value is identified. -- [ ] Create `docs/adrs/<YYYYMMDDHHMMSS>_ai-agent-framework-approach.md` using the `create-adr` skill -- [ ] Record the decision, the alternatives considered, and the reasoning above +- [x] Create `docs/adrs/<YYYYMMDDHHMMSS>_ai-agent-framework-approach.md` using the `create-adr` skill +- [x] Record the decision, the alternatives considered, and the reasoning above Commit message: `docs(adrs): add ADR for AI agent framework approach` diff --git a/project-words.txt b/project-words.txt index 00939a1ba..2f9b7921d 100644 --- a/project-words.txt +++ b/project-words.txt @@ -246,6 +246,7 @@ sysmalloc sysret timespec toki +specialised toplevel torru ttwu From 14b6135ecf0f4bfd8ec7ee26a29d8d1d1db8431f Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 07:58:14 +0100 Subject: [PATCH 67/79] docs(agents): fix inconsistencies found in Copilot PR review (#1697) - Fix malformed YAML frontmatter in write-unit-test SKILL.md (file path prepended to opening delimiter; fix metadata field indentation) - Remove stale cSpell.json reference from run-linters/references/linters.md - Remove located-error and clock from Utilities/Test-support layer in packages/AGENTS.md (already listed in Domain/Shared) - Update AGENTS.md: remove #1697 placeholders for .github/skills/ and .github/agents/ entries; remove cSpell.json from config table; fix nightly toolchain comment; update Auto-Invoke Skills section; fix Quick Navigation table last two rows to proper links --- .../run-linters/references/linters.md | 2 +- .../dev/testing/write-unit-test/SKILL.md | 7 ++-- AGENTS.md | 39 ++++++++++--------- packages/AGENTS.md | 2 +- scripts/pre-commit.sh | 4 +- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/.github/skills/dev/git-workflow/run-linters/references/linters.md b/.github/skills/dev/git-workflow/run-linters/references/linters.md index 11795196d..40b3ee5fb 100644 --- a/.github/skills/dev/git-workflow/run-linters/references/linters.md +++ b/.github/skills/dev/git-workflow/run-linters/references/linters.md @@ -52,7 +52,7 @@ Key formatting settings: ### cspell (Spell Checker) **Tool**: cspell -**Config**: `cspell.json`, `cSpell.json` +**Config**: `cspell.json` **Dictionary**: `project-words.txt` **Run**: `linter cspell` diff --git a/.github/skills/dev/testing/write-unit-test/SKILL.md b/.github/skills/dev/testing/write-unit-test/SKILL.md index 3d4569bd5..14df7cce3 100644 --- a/.github/skills/dev/testing/write-unit-test/SKILL.md +++ b/.github/skills/dev/testing/write-unit-test/SKILL.md @@ -1,10 +1,9 @@ -.github/skills/dev/testing/write-unit-test/SKILL.md--- +--- name: write-unit-test description: Guide for writing unit tests following project conventions including behavior-driven naming (it*should*\*), AAA pattern, MockClock for deterministic time testing, and parameterized tests with rstest. Use when adding tests for domain entities, value objects, utilities, or tracker logic. Triggers on "write unit test", "add test", "test coverage", "unit testing", or "add unit tests". metadata: -author: torrust -version: "1.0" - + author: torrust + version: "1.0" --- # Writing Unit Tests diff --git a/AGENTS.md b/AGENTS.md index 9ad7e360a..801bf8eef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,8 +47,8 @@ native IPv4/IPv6 support, private/whitelisted mode, and a management REST API. - `share/default/` — Default configuration files and fixtures - `storage/` — Runtime data (git-ignored); databases, logs, config - `.github/workflows/` — CI/CD workflows (testing, coverage, container, deployment) -- `.github/skills/` — Agent Skills for specialized workflows _(to be added — see issue #1697)_ -- `.github/agents/` — Custom Copilot agents _(to be added — see issue #1697)_ +- `.github/skills/` — Agent Skills for specialized workflows and task-specific guidance +- `.github/agents/` — Custom Copilot agents and their repository-specific definitions ## 📦 Package Catalog @@ -106,19 +106,19 @@ All packages live under `packages/`. The workspace version is `3.0.0-develop`. ## 📄 Key Configuration Files -| File | Used by | -| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| `.markdownlint.json` | markdownlint | -| `.yamllint-ci.yml` | yamllint | -| `.taplo.toml` | taplo (TOML formatting) | -| `cspell.json` / `cSpell.json` | cspell (spell checker) — both filenames exist in the repo | -| `project-words.txt` | cspell project-specific dictionary | -| `rustfmt.toml` | rustfmt (`group_imports = "StdExternalCrate"`, `max_width = 130`) | -| `.cargo/config.toml` | Cargo aliases (`cov`, `cov-lcov`, `cov-html`, `time`) and global `rustflags` (`-D warnings`, `-D unused`, `-D rust-2018-idioms`, …) | -| `Cargo.toml` | Cargo workspace root | -| `compose.yaml` | Docker Compose for local dev and demo | -| `Containerfile` | Container image definition | -| `codecov.yaml` | Code coverage configuration | +| File | Used by | +| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `.markdownlint.json` | markdownlint | +| `.yamllint-ci.yml` | yamllint | +| `.taplo.toml` | taplo (TOML formatting) | +| `cspell.json` | cspell (spell checker) configuration | +| `project-words.txt` | cspell project-specific dictionary | +| `rustfmt.toml` | rustfmt (`group_imports = "StdExternalCrate"`, `max_width = 130`) | +| `.cargo/config.toml` | Cargo aliases (`cov`, `cov-lcov`, `cov-html`, `time`) and global `rustflags` (`-D warnings`, `-D unused`, `-D rust-2018-idioms`, …) | +| `Cargo.toml` | Cargo workspace root | +| `compose.yaml` | Docker Compose for local dev and demo | +| `Containerfile` | Container image definition | +| `codecov.yaml` | Code coverage configuration | ## 🧪 Build & Test @@ -127,7 +127,7 @@ All packages live under `packages/`. The workspace version is `3.0.0-develop`. ```sh rustup show # Check active toolchain rustup update # Update toolchain -rustup toolchain install nightly # Required: pre-commit hooks use cargo +nightly fmt/check/doc +rustup toolchain install nightly # Optional: only needed for manual cargo +nightly doc; the repo hook runs ./scripts/pre-commit.sh ``` ### Build @@ -349,7 +349,8 @@ See [docs/containers.md](docs/containers.md) for detailed container documentatio ## 🎯 Auto-Invoke Skills -Agent Skills will be available under `.github/skills/` once issue #1697 is implemented. +Agent Skills live under [`.github/skills/`](.github/skills/). Each skill is a `SKILL.md` file +with YAML frontmatter and Markdown instructions covering a repeatable workflow. > Skills supplement (not replace) the rules in this file. Rules apply always; skills activate > when their workflows are needed. @@ -384,5 +385,5 @@ Agent Skills will be available under `.github/skills/` once issue #1697 is imple | Run profiling | [`docs/profiling.md`](docs/profiling.md) | | Understand the release process | [`docs/release_process.md`](docs/release_process.md) | | Report a security vulnerability | [`SECURITY.md`](SECURITY.md) | -| Agent skills reference | `.github/skills/` _(coming — see issue #1697)_ | -| Custom agents reference | `.github/agents/` _(coming — see issue #1697)_ | +| Agent skills reference | [`.github/skills/`](.github/skills/) | +| Custom agents reference | [`.github/agents/`](.github/agents/) | diff --git a/packages/AGENTS.md b/packages/AGENTS.md index d3a7dae9d..9f91823c3 100644 --- a/packages/AGENTS.md +++ b/packages/AGENTS.md @@ -28,7 +28,7 @@ depend on packages in the same layer or a lower one. │ events metrics clock located-error server-lib │ ├────────────────────────────────────────────────────────────────┤ │ Utilities / Test support │ -│ test-helpers located-error clock │ +│ test-helpers │ └────────────────────────────────────────────────────────────────┘ ``` diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index 04dec26f4..c360ad6b6 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -49,7 +49,9 @@ run_step() { echo "[Step ${step_number}/${total_steps}] ${description}..." local step_start=$SECONDS - eval "${command}" + local -a cmd_array + read -ra cmd_array <<< "${command}" + "${cmd_array[@]}" local step_elapsed=$((SECONDS - step_start)) echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))" From a71ac074a32fba386f4eeb3be0379586798a9043 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 08:11:37 +0100 Subject: [PATCH 68/79] docs(issues): mark issue #1697 as fully complete --- docs/issues/1697-ai-agent-configuration.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index de84fb175..925f04ea5 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -192,7 +192,7 @@ tasks can be delegated to focused agents with the right prompt context. - [x] For each agent, create `.github/agents/<agent-name>.md` with: - YAML frontmatter: `name` (optional), `description`, optional `tools` - Prompt body: role definition, scope, constraints, and step-by-step instructions -- [ ] Test each custom agent by assigning it to a task or issue in GitHub Copilot CLI +- [x] Test each custom agent by assigning it to a task or issue in GitHub Copilot CLI **Candidate initial agents**: @@ -349,10 +349,10 @@ Checkpoint: ## Acceptance Criteria -- [ ] `AGENTS.md` exists at the repo root and contains accurate, up-to-date project guidance. -- [ ] At least one skill is available under `.github/skills/` and can be successfully activated by GitHub Copilot. -- [ ] At least one custom agent is available under `.github/agents/` and can be assigned to a task. -- [ ] `copilot-setup-steps.yml` exists, the workflow runs successfully in the **Actions** tab, and `linter all` exits with code `0` inside it. -- [ ] An ADR exists in `docs/adrs/` documenting the decision to use a custom GitHub-Copilot-aligned agent framework. -- [ ] All files pass spelling checks (`cspell`) and markdown linting. -- [ ] A brief entry in `docs/index.md` points contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/`. +- [x] `AGENTS.md` exists at the repo root and contains accurate, up-to-date project guidance. +- [x] At least one skill is available under `.github/skills/` and can be successfully activated by GitHub Copilot. +- [x] At least one custom agent is available under `.github/agents/` and can be assigned to a task. +- [x] `copilot-setup-steps.yml` exists, the workflow runs successfully in the **Actions** tab, and `linter all` exits with code `0` inside it. +- [x] An ADR exists in `docs/adrs/` documenting the decision to use a custom GitHub-Copilot-aligned agent framework. +- [x] All files pass spelling checks (`cspell`) and markdown linting. +- [x] A brief entry in `docs/index.md` points contributors to `AGENTS.md`, `.github/skills/`, and `.github/agents/`. From 492a8ac37ae1cfb6719721da5ad59a45c9963f08 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 08:41:28 +0100 Subject: [PATCH 69/79] fix(agents): address second-round Copilot PR review suggestions (#1697) - Fix install-git-hooks.sh: use git rev-parse --git-path hooks for HOOKS_DST to support git worktrees; add mkdir -p to ensure dir exists - Fix project-words.txt: restore alphabetical order for penalise (after peerlist), repomix (in re* section before repr), specialised (between socketaddr and sqllite), and toplevel (between tlsv and Torrentstorm); remove duplicates from near-end of file - Fix copilot-setup-steps.yml: expand push/pull_request path triggers to include scripts/install-git-hooks.sh and scripts/pre-commit.sh --- .github/workflows/copilot-setup-steps.yml | 4 ++++ project-words.txt | 8 ++++---- scripts/install-git-hooks.sh | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 141cf8df4..2017038b9 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -7,9 +7,13 @@ on: push: paths: - .github/workflows/copilot-setup-steps.yml + - scripts/install-git-hooks.sh + - scripts/pre-commit.sh pull_request: paths: - .github/workflows/copilot-setup-steps.yml + - scripts/install-git-hooks.sh + - scripts/pre-commit.sh jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up diff --git a/project-words.txt b/project-words.txt index 2f9b7921d..9458ebbf3 100644 --- a/project-words.txt +++ b/project-words.txt @@ -127,9 +127,9 @@ obra oneshot ostr Pando -penalise peekable peerlist +penalise programatik proot proto @@ -140,6 +140,7 @@ Rasterbar realpath reannounce Registar +repomix repr reqs reqwest @@ -149,7 +150,6 @@ ringsize rngs rosegment routable -repomix rstest rusqlite rustc @@ -166,6 +166,7 @@ SHLVL skiplist slowloris socketaddr +specialised sqllite subsec Swatinem @@ -178,6 +179,7 @@ testcontainers Tera thiserror tlsv +toplevel Torrentstorm torrust torrustracker @@ -246,8 +248,6 @@ sysmalloc sysret timespec toki -specialised -toplevel torru ttwu uninit diff --git a/scripts/install-git-hooks.sh b/scripts/install-git-hooks.sh index 8762bc88c..478377791 100755 --- a/scripts/install-git-hooks.sh +++ b/scripts/install-git-hooks.sh @@ -11,7 +11,8 @@ set -euo pipefail REPO_ROOT="$(git rev-parse --show-toplevel)" HOOKS_SRC="${REPO_ROOT}/.githooks" -HOOKS_DST="${REPO_ROOT}/.git/hooks" +HOOKS_DST="$(git rev-parse --git-path hooks)" +mkdir -p "${HOOKS_DST}" if [ ! -d "${HOOKS_SRC}" ]; then echo "ERROR: .githooks/ directory not found at ${HOOKS_SRC}" From 4fc97a08e5e3235dccb7cd42cb52c383dcb11afd Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 09:52:10 +0100 Subject: [PATCH 70/79] fix(agents): correct package names and clock API in skills (#1697) - Fix MySQL test commands: replace torrust-tracker-core / tracker-core with the correct Cargo package name bittorrent-tracker-core in packages/AGENTS.md and run-pre-commit-checks/SKILL.md - Fix write-unit-test/SKILL.md: replace fictional Arc<dyn Clock> injection pattern and MockClock::new() constructor with the real type-level CurrentClock alias (clock::Working / clock::Stopped) and Stopped::local_set() for deterministic time in tests; also fix cargo test -p tracker-core -> bittorrent-tracker-core and update quick checklist --- .../run-pre-commit-checks/SKILL.md | 2 +- .../dev/testing/write-unit-test/SKILL.md | 79 ++++++++++++------- packages/AGENTS.md | 2 +- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md index 8e19eee0e..b0eb24e4d 100644 --- a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md +++ b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md @@ -43,7 +43,7 @@ The script runs these steps in order: > **MySQL tests**: MySQL-specific tests require a running instance and a feature flag: > > ```bash -> TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test --package tracker-core +> TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test --package bittorrent-tracker-core > ``` > > These are not run by the pre-commit script. diff --git a/.github/skills/dev/testing/write-unit-test/SKILL.md b/.github/skills/dev/testing/write-unit-test/SKILL.md index 14df7cce3..5ba1a8381 100644 --- a/.github/skills/dev/testing/write-unit-test/SKILL.md +++ b/.github/skills/dev/testing/write-unit-test/SKILL.md @@ -90,7 +90,7 @@ mod tests { ```bash # Run all tests in a package -cargo test -p tracker-core +cargo test -p bittorrent-tracker-core # Run specific test by name cargo test it_should_return_error_when_info_hash_is_invalid @@ -102,61 +102,82 @@ cargo test info_hash::tests cargo test -- --nocapture ``` -## Phase 2: Deterministic Time with MockClock +## Phase 2: Deterministic Time with `clock::Stopped` -The `clock` workspace package provides a `MockClock` for deterministic time testing. -Never use `std::time::SystemTime::now()` or `chrono::Utc::now()` directly in production code -that needs testing. +The `clock` workspace package provides `clock::Stopped` for deterministic time testing. +Never call `std::time::SystemTime::now()` or `chrono::Utc::now()` directly in production code +that needs testing. Instead, use the type-level clock abstraction. -### Inject the Clock Dependency +### Use the Type-Level Clock Alias + +Copy the following boilerplate into each crate that needs a clock. The `CurrentClock` alias +automatically selects `Working` in production and `Stopped` in tests: ```rust -use torrust_tracker_clock::clock::Clock; -use std::sync::Arc; +/// Working version, for production. +#[cfg(not(test))] +pub(crate) type CurrentClock = torrust_tracker_clock::clock::Working; -pub struct PeerList { - clock: Arc<dyn Clock>, -} +/// Stopped version, for testing. +#[cfg(test)] +pub(crate) type CurrentClock = torrust_tracker_clock::clock::Stopped; +``` -impl PeerList { - pub fn new(clock: Arc<dyn Clock>) -> Self { - Self { clock } - } +In production code, obtain the current time via the `Time` trait: - pub fn is_peer_expired(&self, last_seen: i64, ttl: u32) -> bool { - let now = self.clock.now(); - now - last_seen > i64::from(ttl) - } +```rust +use torrust_tracker_clock::clock::Time as _; + +pub fn is_peer_expired(last_seen: std::time::Duration, ttl: u32) -> bool { + let now = CurrentClock::now(); // returns DurationSinceUnixEpoch (= std::time::Duration) + now.saturating_sub(last_seen) > std::time::Duration::from_secs(u64::from(ttl)) } ``` -### Use MockClock in Tests +### Control Time in Tests + +Use `clock::Stopped::local_set` to pin the clock to a specific instant. The stopped clock is +thread-local, so tests are isolated from each other by default. ```rust #[cfg(test)] mod tests { + use std::time::Duration; + + use torrust_tracker_clock::clock::{stopped::Stopped as _, Time as _}; + use torrust_tracker_clock::clock::Stopped; + use super::*; - use torrust_tracker_clock::clock::stopped::Stopped as MockClock; - use std::sync::Arc; #[test] fn it_should_mark_peer_as_expired_when_ttl_has_elapsed() { - // Arrange - let fixed_time = 1_700_000_100i64; // specific Unix timestamp - let clock = Arc::new(MockClock::new(fixed_time)); - let list = PeerList::new(clock); - let last_seen = 1_700_000_000i64; + // Arrange — pin the clock to a known instant + let fixed_time = Duration::from_secs(1_700_000_100); + Stopped::local_set(&fixed_time); + + let last_seen = Duration::from_secs(1_700_000_000); let ttl = 60u32; // Act - let expired = list.is_peer_expired(last_seen, ttl); + let expired = is_peer_expired(last_seen, ttl); // Assert assert!(expired); + + // Clean up — reset to zero so other tests start from a clean state + Stopped::local_reset(); } } ``` +> **Key points** +> +> - `Stopped::now()` defaults to `Duration::ZERO` at the start of each test thread. +> - `Stopped::local_set(&duration)` sets the current time for the calling thread only. +> - `Stopped::local_reset()` resets back to `Duration::ZERO`. +> - `Stopped::local_add(&duration)` advances the clock by the given amount. +> - Import the `Stopped` trait (`use …::stopped::Stopped as _`) to bring its methods into scope. + ## Phase 3: Parameterized Tests with rstest Use `rstest` for multiple input/output combinations to avoid repetition. @@ -195,6 +216,6 @@ Check the package for available mock servers, fixture generators, and utility ty - [ ] Test name uses `it_should_` prefix - [ ] Test follows AAA pattern with comments (`// Arrange`, `// Act`, `// Assert`) -- [ ] No `std::time::SystemTime::now()` in production code — inject `Clock` instead +- [ ] No `std::time::SystemTime::now()` in production code — use the `CurrentClock` type alias instead - [ ] No shared mutable state between tests - [ ] `cargo test -p <package>` passes diff --git a/packages/AGENTS.md b/packages/AGENTS.md index 9f91823c3..231bfe3a9 100644 --- a/packages/AGENTS.md +++ b/packages/AGENTS.md @@ -134,7 +134,7 @@ cargo test -p <package-name> cargo test --doc -p <package-name> # MySQL-specific tests in tracker-core (requires a running MySQL instance) -TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test -p torrust-tracker-core +TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test -p bittorrent-tracker-core ``` Use `clock::Stopped` (from the `clock` package) in unit tests that need deterministic time. From de41a577421bba2af2e04b579d1afe03461ee4ab Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 21:57:21 +0100 Subject: [PATCH 71/79] docs(issues): add implementation specs for EPIC #1525 overhaul persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the EPIC planning doc and eight sub-issue specs covering the full persistence overhaul: - #1525: EPIC – Overhaul Persistence (delivery strategy + ordering) - #1525-01: Persistence test coverage (DB compatibility matrix) - #1525-02: qBittorrent E2E test runner - #1525-03: Persistence benchmarking framework - #1525-04: Split persistence traits (narrow interfaces) - #1525-05: Migrate SQLite and MySQL drivers to sqlx - #1525-07: Align Rust and DB types (u32→u64, INTEGER→BIGINT) - #1525-08: Add PostgreSQL driver Also adds new technical terms to project-words.txt (dbname, isready, VARCHAR) required for the cspell spell-checker to pass. --- .../1525-01-persistence-test-coverage.md | 155 ++++ docs/issues/1525-02-qbittorrent-e2e.md | 184 +++++ .../1525-03-persistence-benchmarking.md | 251 ++++++ .../1525-04-split-persistence-traits.md | 281 +++++++ ...525-05-migrate-sqlite-and-mysql-to-sqlx.md | 280 +++++++ .../1525-06-introduce-schema-migrations.md | 429 +++++++++++ .../issues/1525-07-align-rust-and-db-types.md | 228 ++++++ docs/issues/1525-08-add-postgresql-driver.md | 723 ++++++++++++++++++ docs/issues/1525-overhaul-persistence.md | 150 ++++ project-words.txt | 13 + 10 files changed, 2694 insertions(+) create mode 100644 docs/issues/1525-01-persistence-test-coverage.md create mode 100644 docs/issues/1525-02-qbittorrent-e2e.md create mode 100644 docs/issues/1525-03-persistence-benchmarking.md create mode 100644 docs/issues/1525-04-split-persistence-traits.md create mode 100644 docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md create mode 100644 docs/issues/1525-06-introduce-schema-migrations.md create mode 100644 docs/issues/1525-07-align-rust-and-db-types.md create mode 100644 docs/issues/1525-08-add-postgresql-driver.md create mode 100644 docs/issues/1525-overhaul-persistence.md diff --git a/docs/issues/1525-01-persistence-test-coverage.md b/docs/issues/1525-01-persistence-test-coverage.md new file mode 100644 index 000000000..9baf1102e --- /dev/null +++ b/docs/issues/1525-01-persistence-test-coverage.md @@ -0,0 +1,155 @@ +# Subissue Draft for #1525-01: Add DB Compatibility Matrix + +## Goal + +Establish a compatibility matrix that exercises persistence-layer tests across supported database +versions before any refactoring begins. + +## Why First + +The later refactors change persistence architecture, async behavior, schema setup, and backend +implementations. Running the tests against multiple database versions first gives a baseline to +detect regressions early and narrows review scope to behavior rather than guesswork. + +## Scope + +- Bash is acceptable for low-complexity orchestration. +- Focus only on the database compatibility matrix; end-to-end real-client testing is covered by + subissue #1525-02. + +## Testing Principles + +The implementation must follow these quality rules for all new and modified tests. + +- **Isolation**: Each test run must be independent. Tests that spin up database containers via + `testcontainers` already get their own ephemeral container; the bash matrix script achieves + isolation by running one matrix cell at a time in a fresh process, each with an exclusively + allocated container. +- **Independent system resources**: Tests must not hard-code host ports. `testcontainers` binds + containers to random free host ports automatically — do not override this with fixed bindings. + Temporary files or directories, if needed, must be created under a `tempfile`-managed path so + they are always removed on exit. +- **Cleanup**: After each test (success or failure) all containers, volumes, and temporary files + must be released. `testcontainers` handles containers automatically when the handle is dropped; + ensure `Drop` is not suppressed. +- **Behavior, not implementation**: Tests must assert observable outcomes (e.g. the driver + correctly inserts and retrieves a torrent entry) rather than internal state (e.g. a specific SQL + query was issued). +- **Verified before done**: No test is considered complete until it has been executed and passes + in a clean environment. Include confirmation of a passing run in the PR description. + +## Reference QA Workflow + +The PR #1695 review branch includes a QA script that defines the expected behavior: + +- `run-db-compatibility-matrix.sh`: + executes a compatibility matrix across SQLite, multiple MySQL versions, and multiple PostgreSQL + versions. + +This should be treated as a reference prototype, not a production artifact. The goal is to +re-implement it in a form that integrates with the repository's normal test strategy. + +## Dependency Note + +PostgreSQL is not implemented yet, so this subissue cannot require successful execution against +PostgreSQL. The structure should make it easy to add PostgreSQL combinations in subissue +`#1525-08` once the driver exists. + +## Proposed Branch + +- `1525-01-db-compatibility-matrix` + +## Tasks + +### 1) Port the compatibility matrix workflow + +Add a low-complexity bash compatibility-matrix runner that exercises persistence-related tests +across supported database versions. + +Tests to orchestrate: + +- `cargo check --workspace --all-targets` +- configuration coverage for PostgreSQL connection settings +- large-download counter saturation tests in the HTTP protocol layer +- large-download counter saturation tests in the UDP protocol layer +- SQLite driver tests +- MySQL driver tests across selected MySQL versions + +Note: PostgreSQL version-matrix execution is deferred to subissue #1525-08, once the +PostgreSQL driver exists. + +Steps: + +- Modify current DB driver tests so the DB image version can be injected through environment + variables: + - MySQL: `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG` + - PostgreSQL (reserved for subissue #1525-08): `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG` + + When `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG` is not set, the test falls back to the + current hardcoded default (e.g. `8.0`), preserving existing behavior. The matrix script sets + this variable explicitly for each version in the loop, so unset means "run as today" and the + matrix just expands that into multiple combinations. + +- Add `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` modeled after the PR prototype: + - `set -euo pipefail` + - define default version sets from env vars: + - `MYSQL_VERSIONS` defaulting to at least `8.0 8.4` + - `POSTGRES_VERSIONS` reserved for subissue #1525-08 + - run pre-checks once (`cargo check --workspace --all-targets`) + - run protocol/configuration tests once + - run SQLite driver tests once + - loop MySQL versions: `docker pull mysql:<version>`, then run MySQL driver tests with + `TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=1` and + `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG=<version>` + - print a clear heading for each backend/version before executing tests + - fail fast on first failure with the failing backend/version visible in logs + - keep script complexity intentionally low; avoid re-implementing test logic already in test + functions +- Replace the current single MySQL `database` step in `.github/workflows/testing.yaml` with + execution of the new script. + +Acceptance criteria: + +- [ ] DB image version injection is supported via `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG` + (and a reserved `POSTGRES` equivalent for subissue #1525-08). +- [ ] `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` exists and runs successfully. +- [ ] The script exercises SQLite and at least two MySQL versions by default. +- [ ] Failures identify the backend/version combination that broke. +- [ ] The `database` job step in `.github/workflows/testing.yaml` runs the matrix script instead + of a single-version MySQL command. +- [ ] The script structure allows PostgreSQL to be added in subissue #1525-08 without a redesign. +- [ ] Tests do not hard-code host ports; `testcontainers` assigns random ports automatically. +- [ ] All containers started by tests are removed unconditionally on test completion or failure. + +### 2) Document the workflow + +Steps: + +- Document the local invocation command for the matrix script. +- Document that the CI `database` step runs the same script. + +Acceptance criteria: + +- [ ] The matrix script is documented and runnable without ad hoc manual steps. + +## Out of Scope + +- qBittorrent end-to-end testing (covered by subissue #1525-02). +- Adding PostgreSQL support itself. +- Refactoring the production persistence interfaces. +- Performance benchmarking, before/after comparison, and benchmark reporting. + +## Definition of Done + +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. +- [ ] The matrix script has been executed successfully in a clean environment; a passing run log + is included in the PR description. + +## References + +- EPIC: #1525 +- Reference PR: #1695 +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference script: `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` diff --git a/docs/issues/1525-02-qbittorrent-e2e.md b/docs/issues/1525-02-qbittorrent-e2e.md new file mode 100644 index 000000000..447b4ecc9 --- /dev/null +++ b/docs/issues/1525-02-qbittorrent-e2e.md @@ -0,0 +1,184 @@ +# Subissue Draft for #1525-02: Add qBittorrent End-to-End Test + +## Goal + +Add a high-level end-to-end test that validates tracker behavior through a complete torrent-sharing +scenario using real containerized BitTorrent clients, covering scenarios that lower-level unit and +integration tests cannot reach. + +## Why Before the Refactor + +The persistence refactor changes storage behavior underneath the tracker. Having a real-client +scenario that exercises a full download cycle (seeder uploads → leecher downloads → tracker +records completion) gives a regression backstop that is not possible with protocol-level tests +alone. + +## Scope + +- Follow the same pattern as the existing `e2e_tests_runner` binary + (`src/console/ci/e2e/runner.rs`): a Rust binary that drives the whole scenario using + `std::process::Command` to invoke `docker compose` and any container-side commands. +- Use SQLite as the database backend; database compatibility across multiple versions is already + covered by subissue #1525-01. +- Cover one complete scenario: a seeder sharing a torrent that a leecher downloads in full. +- The binary is responsible for scaffolding (generating a temporary config and torrent file), + starting the services, sending commands into the qBittorrent containers (via their WebUI API + or `docker exec`), polling for completion, asserting the result, and tearing down. +- Do not re-test things already covered at a lower level: announce parsing, scrape format, + whitelist/key logic, or multi-database compatibility. + +## Testing Principles + +The implementation must follow these quality rules. + +- **Isolation**: Each run of the E2E binary must be isolated from any other concurrently running + instance. Achieve this by using a unique Docker Compose project name per run (e.g. + `--project-name qbt-e2e-<random-suffix>`) so container names, networks, and volumes never + collide with a parallel run. +- **Independent system resources**: Do not bind services to fixed host ports. Let Docker assign + ephemeral host ports and discover them from the compose output, so two simultaneous runs cannot + conflict. Place all temporary files (tracker config, payload, `.torrent` file) in a + `tempfile`-managed directory created at runner start and deleted on exit. +- **Cleanup**: `docker compose down --volumes` must be called unconditionally — on success, on + assertion failure, and on panic. Use a Rust `Drop` guard or equivalent to guarantee teardown + even when the runner exits unexpectedly. +- **Mock time when possible**: Use a configurable timeout (CLI argument or env var) for the + leecher-completion poll rather than a hard-coded sleep. If any logic depends on wall-clock time + (e.g. stale peer detection), inject a mockable clock consistent with the `clock` package used + elsewhere in the codebase. +- **Behavior, not implementation**: Assert the outcome the user cares about — the leecher holds a + complete, byte-identical copy of the payload — not which internal tracker counters changed or + which announce endpoints were called. +- **Verified before done**: The binary must be executed end-to-end and produce a passing result in + a clean environment before the subissue is closed. Include a run log in the PR description. + +## Reference QA Workflow + +`contrib/dev-tools/qa/run-qbittorrent-e2e.py` in the PR #1695 review branch demonstrates the +scenario (seeder + leecher + tracker via Python subprocess). Treat it as a behavioral reference +only; the implementation here will use `docker compose` instead of manual container management. + +## Proposed Branch + +- `1525-02-qbittorrent-e2e` + +## Tasks + +### 1) Add a docker compose file for the E2E scenario + +Add a compose file (e.g., `compose.qbittorrent-e2e.yaml`) that defines: + +- the tracker service configured with SQLite +- a qbittorrent-seeder container +- a qbittorrent-leecher container + +Steps: + +- Define a tracker service mounting a SQLite config file (generated by the runner). +- Define seeder and leecher services using a suitable qBittorrent image. +- Configure a shared network so all containers can reach each other and the tracker. +- Define any volumes needed to mount the payload and torrent file into each client container. +- Ensure `docker compose up --wait` exits cleanly when services are healthy. +- Ensure `docker compose down --volumes` removes all containers and volumes. + +Acceptance criteria: + +- [ ] `docker compose -f compose.qbittorrent-e2e.yaml up --wait` starts all services without error. +- [ ] `docker compose -f compose.qbittorrent-e2e.yaml down --volumes` leaves no orphaned resources. + +### 2) Implement the Rust runner binary + +Add a new binary (e.g., `src/bin/qbittorrent_e2e_runner.rs`) that follows the same structure as +`src/console/ci/e2e/runner.rs`: + +- Parses CLI arguments or environment variables (compose file path, payload size, timeout). +- Generates scaffolding: a temporary tracker config (SQLite) and a small deterministic payload + with its `.torrent` file. +- Calls `docker compose up` via `std::process::Command`. +- Seeds the payload: injects the torrent and payload into the seeder container via the qBittorrent + WebUI REST API (or `docker exec` as a fallback) and starts seeding. +- Leaches the payload: injects the `.torrent` file into the leecher container and starts + downloading. +- Polls for completion: queries the leecher's WebUI API until the torrent state reaches + `uploading` (100 % downloaded) or a timeout expires. +- Asserts payload integrity: compares the downloaded file against the original (hash or byte + comparison). +- Calls `docker compose down --volumes` unconditionally (even on assertion failure), mirroring + the cleanup pattern in `tracker_container.rs`. + +Steps: + +- Add a shared `docker compose` wrapper at `src/console/ci/compose.rs` (see below). This + module is not specific to qBittorrent and is reused by the benchmark runner in subissue + `#1525-03`. +- Add a `qbittorrent` module under `src/console/ci/` (parallel to `e2e/`) containing: + - `runner.rs` — main orchestration logic + - `qbittorrent_client.rs` — HTTP calls to the qBittorrent WebUI API +- **`src/console/ci/compose.rs` wrapper** — mirrors `docker.rs` but targets `docker compose` + subcommands. Design it around a `DockerCompose` struct that holds the compose file path and + project name: + - `DockerCompose::new(file: &Path, project: &str) -> Self` + - `up(&self) -> io::Result<()>` — runs `docker compose -f <file> -p <project> up --wait --detach` + - `down(&self) -> io::Result<()>` — runs `docker compose -f <file> -p <project> down --volumes` + - `port(&self, service: &str, container_port: u16) -> io::Result<u16>` — runs + `docker compose -f <file> -p <project> port <service> <port>` and parses the host port so + the runner never hard-codes ports + - `exec(&self, service: &str, cmd: &[&str]) -> io::Result<Output>` — wraps + `docker compose -f <file> -p <project> exec <service> <cmd…>` for injecting commands into + running containers + - Implement `Drop` on a `RunningCompose` guard returned by `up` that calls `down` + unconditionally, matching the `RunningContainer::drop` pattern in `docker.rs` + - Use `tracing` for progress output consistent with the rest of the runner +- Generate a fixed small payload (e.g., 1 MiB of deterministic bytes) at runtime; store the + `.torrent` file in a `tempfile` directory so it is cleaned up automatically. +- Re-use `tracing` for progress output, consistent with the existing runner. + +Acceptance criteria: + +- [ ] The runner completes a full seeder → leecher download using the containerized tracker. +- [ ] Payload integrity is verified after download (hash or byte comparison). +- [ ] The runner can be executed repeatedly without manual setup or teardown. +- [ ] No orphaned containers or volumes remain on success or failure. +- [ ] The binary is documented in the top-level module doc comment with an example invocation. +- [ ] Each invocation uses a unique compose project name so parallel runs do not conflict. +- [ ] All temporary files are placed in a managed temp directory and deleted on exit. +- [ ] No fixed host ports are used; ports are discovered dynamically from the compose output. +- [ ] `docker compose down --volumes` is called unconditionally via a `Drop` guard. + +### 3) Document the E2E workflow + +Steps: + +- Document the local invocation command (e.g., `cargo run --bin qbittorrent_e2e_runner`). +- Document any prerequisites (Docker, image availability, open ports). +- Clarify that this test is not run in the standard `cargo test` suite due to resource + requirements and describe how it is triggered in CI (opt-in env var or separate job). + +Acceptance criteria: + +- [ ] The test is documented and runnable without ad hoc manual steps. + +## Out of Scope + +- Testing multiple database backends (covered by subissue #1525-01). +- Testing announce or scrape protocol correctness at the protocol level. +- UDP tracker E2E (can be added later without redesigning the compose setup). + +## Definition of Done + +- [ ] `cargo test --workspace --all-targets` passes (or the E2E test is explicitly excluded with a + documented opt-in flag). +- [ ] `linter all` exits with code `0`. +- [ ] The E2E runner has been executed successfully in a clean environment; a passing run log is + included in the PR description. + +## References + +- EPIC: #1525 +- Reference PR: #1695 +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference script: `contrib/dev-tools/qa/run-qbittorrent-e2e.py` +- Existing runner pattern: `src/console/ci/e2e/runner.rs` +- Docker command wrapper: `src/console/ci/e2e/docker.rs` +- Existing container wrapper patterns: `src/console/ci/e2e/tracker_container.rs` diff --git a/docs/issues/1525-03-persistence-benchmarking.md b/docs/issues/1525-03-persistence-benchmarking.md new file mode 100644 index 000000000..d1b3ec32b --- /dev/null +++ b/docs/issues/1525-03-persistence-benchmarking.md @@ -0,0 +1,251 @@ +# Subissue Draft for #1525-03: Add Persistence Benchmarking + +## Goal + +Establish reproducible before/after persistence benchmarks so later refactors can be evaluated +against a concrete performance baseline. + +## Why After Testing + +Correctness comes first. Benchmarking is useful only after the core persistence behaviors are +already covered by tests, otherwise performance comparisons risk masking regressions in behavior. + +## Scope + +- Implement the benchmark runner in Rust (a new binary, consistent with the `e2e_tests_runner` + pattern), following the same docker compose approach used in subissue #1525-02. +- Use one docker compose file per database backend. Each compose file defines the database + container and the tracker container together. The runner launches the compose stack, + discovers the ports, runs the workloads, and tears down. No manual `docker run` calls. +- Run the benchmark against SQLite and MySQL only. PostgreSQL is not available yet; the runner + must be designed so PostgreSQL can be added in subissue #1525-08 without redesign. +- The benchmark compares two tracker Docker images: a `bench-before` image and a `bench-after` + image. The tracker image tag is passed to compose via an environment variable so the runner + can swap it per variant. This allows the same compose files and runner to be re-used after + each subsequent subissue. +- On the first run (this subissue), before and after use the same image built from the current + `develop` HEAD, giving an identical-baseline comparison. The committed report records this. +- Commit the first benchmark report into `docs/benchmarks/` as a baseline reference. Re-run + and update the report in each subsequent subissue that changes persistence behavior. + +## Measurement Tool Rationale + +**Why not Criterion?** `criterion` is a micro-benchmark framework: it runs the same in-process +function thousands of times in a tight loop, applies warm-up phases, and performs statistical +outlier detection for nanosecond-to-millisecond measurements. It is the right tool for the +existing `torrent-repository-benchmarking` crate (in-memory data structures). It is the wrong +tool here because: + +- Each operation involves a real HTTP round-trip to a containerized tracker talking to a real + database. The overhead dwarfs what criterion's sampling model expects. +- We need _aggregate_ metrics across N concurrent workers (ops/sec, p95 latency), not per-call + statistics from a single thread. +- The before/after comparison is across two different Docker images, not across two functions + in the same process — criterion has no model for that. + +**What to use instead**: `std::time::Instant` per-call timing, collected into a `Vec<Duration>`, +then sorted for percentile extraction. This is exactly what the Python reference script does. +For concurrency, spawn N OS threads via `std::thread::spawn` (one per worker up to +`--concurrency`), each running blocking `reqwest` calls in a loop. Join all threads and +collect their `Duration` measurements into a shared `Vec` for percentile computation. Do +not use `rayon` — its work-stealing pool is designed for CPU-bound tasks and will stall +under I/O-bound HTTP workloads. Output is written as JSON (via `serde_json`) and Markdown. + +## Reference Workflow + +The PR #1695 review branch includes a Python reference: + +- `contrib/dev-tools/qa/run-before-after-db-benchmark.py` + +That script defines the full benchmark approach: it starts a real tracker binary, starts +database containers with free ports, sends HTTP workloads concurrently, collects latency +percentiles and throughput, and prints a before/after comparison. The Rust implementation +must replicate this approach. + +### What the Python script measures + +- **Startup time** — how long the tracker takes to reach `200 OK` on the health endpoint, + measured for both an empty database and a populated database (after the workloads have run). +- **Workloads** (each run sequentially and concurrently): + - `announce_lifecycle` — HTTP `started` announce followed by `completed` announce for each + unique infohash + - `whitelist_add` — REST API `POST /api/v1/whitelist/{info_hash}` + - `whitelist_reload` — REST API `GET /api/v1/whitelist/reload` + - `auth_key_add` — REST API `POST /api/v1/keys` + - `auth_key_reload` — REST API `GET /api/v1/keys/reload` +- **Metrics per workload**: count, total time, ops/sec, mean latency, median latency, p95 + latency, min/max latency. +- **Comparison output**: startup speedup (after/before), ops/s speedup, p95 latency improvement + ratio for each workload × driver combination. + +## Proposed Branch + +- `1525-03-persistence-benchmarking` + +## Testing Principles + +- **Isolation**: Each run uses a unique compose project name (e.g. + `torrust-bench-<driver>-<variant>-<random>`) so container names, networks, and volumes + never collide with a parallel invocation. This mirrors the isolation strategy in + subissue #1525-02. +- **Independent system resources**: Do not bind to fixed host ports. Discover the ports + assigned by compose using `docker compose port`. Place all temporary files (SQLite database + file, tracker config, logs) in a `tempfile`-managed directory that is removed on exit. +- **Cleanup**: Use a `RunningCompose` `Drop` guard (from the `DockerCompose` wrapper in + subissue #1525-02) to call `docker compose down --volumes` unconditionally on success, + failure, and panic. +- **Verified before done**: Run the benchmark in a clean environment and include the output in + the PR description alongside the committed report. + +## Tasks + +### 1) Add docker compose files for each database backend + +Add one compose file per database under `contrib/dev-tools/bench/`: + +- `compose.bench-sqlite3.yaml` — tracker service + a volume for the SQLite database file. +- `compose.bench-mysql.yaml` — tracker service + MySQL service. + +Design notes: + +- Parameterize the tracker image tag with an env var (e.g. + `TORRUST_TRACKER_BENCH_IMAGE`, defaulting to `torrust-tracker:bench`) so the runner can + swap before/after images without editing the file. +- Set `TORRUST_TRACKER_CONFIG_TOML` via the compose `environment` key so the runner can inject + a generated config without mounting a file. +- Do not expose fixed host ports in the compose files; expose only the container ports and let + Docker assign ephemeral host ports. The runner discovers them with `docker compose port`. +- Ensure `healthcheck` is defined for each service so `docker compose up --wait` blocks until + everything is ready. + +Acceptance criteria: + +- [ ] `docker compose -f compose.bench-sqlite3.yaml up --wait` starts successfully. +- [ ] `docker compose -f compose.bench-mysql.yaml up --wait` starts successfully. +- [ ] `docker compose -f <file> down --volumes` leaves no orphaned resources. + +### 2) Implement the Rust benchmark runner binary + +Add a new binary `src/bin/persistence_benchmark_runner.rs` following the `e2e_tests_runner` +pattern. Reuse the `DockerCompose` wrapper introduced in subissue #1525-02 at +`src/console/ci/compose.rs`. + +**Dependencies** — add to the workspace `Cargo.toml` and the binary's crate: + +```toml +reqwest = { version = "...", features = ["blocking"] } +serde_json = { version = "..." } +``` + +`rayon` is not needed (see the concurrent workloads approach below). Run `cargo machete` +after to verify no unused dependencies remain. + +**Architecture** — add a module `src/console/ci/bench/` containing: + +- `runner.rs` — main orchestration and CLI argument parsing +- `workloads.rs` — HTTP client calls for each workload (announce, whitelist, auth key) +- `metrics.rs` — `Instant`-based latency collection, sorting, percentile and throughput + computation (no external stats crate needed) +- `report.rs` — JSON (`serde_json`) and Markdown formatting + +**CLI arguments** (mirroring the Python script): + +- `--before-image <tag>` — tracker Docker image for the "before" variant + (default: `torrust-tracker:bench`) +- `--after-image <tag>` — tracker Docker image for the "after" variant + (default: same as `--before-image`) +- `--dbs <sqlite3|mysql>` — space/comma-separated list of drivers (default: `sqlite3 mysql`) +- `--mysql-version <tag>` — MySQL Docker image tag (default `8.4`) +- `--ops <n>` — number of operations per workload (default `200`) +- `--reload-iterations <n>` — iterations for reload workloads (default `30`) +- `--concurrency <n>` — worker threads for concurrent workloads (default `16`) +- `--json-output <path>` — write machine-readable JSON to this path +- `--report-output <path>` — write the human-readable Markdown report to this path + +**Per-suite lifecycle** (one suite = one `(driver, variant)` pair): + +1. Select the compose file for the driver. +2. Build or tag the tracker image as `TORRUST_TRACKER_BENCH_IMAGE` for this variant. +3. Create a unique compose project name. +4. `DockerCompose::up()` — blocks until all services are healthy. +5. Discover the tracker HTTP, REST API, and health check host ports via + `DockerCompose::port()`. +6. Record `startup_empty_ms` (time from `up` call to first successful health check response). +7. Run a warm-up iteration. +8. Run each workload sequentially then concurrently; collect per-operation `Duration` values. +9. Restart the tracker service only (or call `down` then `up` again) to measure + `startup_populated_ms` against the now-populated database. +10. `DockerCompose::down()` — unconditional, via `Drop` guard. + +**HTTP client**: use `reqwest` (blocking feature) for workload calls. + +**Concurrent workloads**: spawn `--concurrency` OS threads via `std::thread::spawn`, each +running blocking `reqwest` calls in a loop; collect per-thread `Duration` measurements into +a shared `Vec` (via `Arc<Mutex<Vec<Duration>>>` or join handles). Do not use `rayon` — +its work-stealing pool blocks under I/O-bound workloads. + +Acceptance criteria: + +- [ ] The binary runs successfully against SQLite and MySQL. +- [ ] Startup times (empty and populated) are recorded for each driver. +- [ ] All five workload families are measured sequentially and concurrently. +- [ ] JSON output schema matches the Python reference (`results`, `comparisons` keys). +- [ ] Human-readable Markdown report is produced. +- [ ] All compose stacks are cleaned up unconditionally via `Drop` guards. +- [ ] No hard-coded host ports; all ports are discovered via `docker compose port`. + +### 3) Commit the baseline benchmark report + +After the binary is working: + +- Build a Docker image from the current `develop` HEAD: + `docker build -t torrust-tracker:bench .` +- Run the benchmark with `--before-image torrust-tracker:bench` and + `--after-image torrust-tracker:bench` (both pointing to the same freshly built image, + producing an identical-baseline comparison). +- Save the JSON output to `docs/benchmarks/baseline.json`. +- Save the Markdown report to `docs/benchmarks/baseline.md`. +- Commit both files as part of this subissue's PR. + +Acceptance criteria: + +- [ ] `docs/benchmarks/baseline.json` and `docs/benchmarks/baseline.md` are committed. +- [ ] The Markdown report is readable without tooling and identifies the git revision used. + +### 4) Document the workflow + +Steps: + +- Document how to invoke the benchmark locally. +- Document how to produce an updated report after each subsequent subissue. +- Note that PostgreSQL support will be added to the benchmark in subissue #1525-08. + +Acceptance criteria: + +- [ ] The benchmark is documented and runnable without ad hoc manual steps. + +## Out of Scope + +- PostgreSQL support (reserved for subissue #1525-08). +- Defining hard performance gates for CI. +- Replacing correctness-focused tests. +- The existing `torrent-repository-benchmarking` criterion micro-benchmarks (those measure + in-memory data structures, not the full persistence stack). + +## Definition of Done + +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. +- [ ] The benchmark has been executed successfully; `docs/benchmarks/baseline.md` and + `docs/benchmarks/baseline.json` are committed. +- [ ] A passing run log is included in the PR description. + +## References + +- EPIC: #1525 +- Reference PR: #1695 +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference script: `contrib/dev-tools/qa/run-before-after-db-benchmark.py` +- Docker compose wrapper: `src/console/ci/e2e/docker.rs` (pattern reused for compose wrapper) +- Subissue #1525-02 compose wrapper: `src/console/ci/compose.rs` diff --git a/docs/issues/1525-04-split-persistence-traits.md b/docs/issues/1525-04-split-persistence-traits.md new file mode 100644 index 000000000..284127643 --- /dev/null +++ b/docs/issues/1525-04-split-persistence-traits.md @@ -0,0 +1,281 @@ +# Subissue Draft for #1525-04: Split Persistence Traits by Context + +## Goal + +Decompose the monolithic `Database` trait into four focused context traits while +keeping `Database` as the unified driver contract, and write an ADR to record the +decision. + +## Background + +`packages/tracker-core/src/databases/mod.rs` defines a single `Database` trait with +19 methods covering four unrelated concerns: schema management, torrent metrics, +whitelist, and authentication keys. This makes the trait long and conflates distinct +responsibilities in one place. + +Two options were considered: + +1. **Replace `Database` with four independent traits** — consumers hold + `Arc<dyn WhitelistStore>` etc. directly. Clean interface segregation, but it loses + the single place that tells a new driver implementor exactly what to build, and it + changes every consumer at once. + +2. **Keep `Database` as an aggregate supertrait** (chosen) — the four narrow traits + exist independently; `Database` is defined as: + + ```rust + pub trait Database: + Sync + Send + SchemaMigrator + TorrentMetricsStore + WhitelistStore + AuthKeyStore {} + ``` + + A blanket impl means any type that implements all four narrow traits automatically + satisfies `Database`. Existing consumers (`Arc<Box<dyn Database>>`) are untouched. + +This preserves both goals: + +- **One place to discover the full driver contract**: `Database` and its four supertrait + bounds tell a new implementor exactly what to write. +- **Compiler-enforced completeness**: adding a fifth supertrait later causes a compile + error in every driver that does not yet implement it. +- **Interface segregation at the consumer level**: the four narrow traits can be used + directly in tests (`MockWhitelistStore` etc.) and optionally as dependency types once + the MSRV allows trait-object upcasting (stabilised in Rust 1.76; current MSRV is 1.72). + +## Proposed Branch + +- `1525-04-split-persistence-traits` + +## Current State + +The starting point (before this subissue): + +```text +packages/tracker-core/src/databases/ + mod.rs ← Database trait (19 methods, all concerns in one block) + driver/ + mod.rs + sqlite.rs ← impl Database for Sqlite { ... 19 methods ... } + mysql.rs ← impl Database for Mysql { ... 19 methods ... } + error.rs + setup.rs +``` + +The four context groups already exist as doc-comment markers inside the trait +(`# Context: Schema`, `# Context: Torrent Metrics`, etc.) — this subissue makes those +boundaries structural. + +## Target State + +```text +packages/tracker-core/src/databases/ + mod.rs ← module declarations, re-exports + database.rs ← Database aggregate trait + blanket impl + schema.rs ← SchemaMigrator trait + torrent_metrics.rs ← TorrentMetricsStore trait + whitelist.rs ← WhitelistStore trait + auth_keys.rs ← AuthKeyStore trait + driver/ + mod.rs + sqlite.rs ← impl SchemaMigrator + TorrentMetricsStore + + WhitelistStore + AuthKeyStore for Sqlite + mysql.rs ← same for Mysql + error.rs + setup.rs +``` + +## Tasks + +### 1) Write the ADR + +Create `docs/adrs/<timestamp>_keep_database_as_aggregate_supertrait.md` recording: + +- The problem (19-method monolith, unclear per-context boundaries). +- The two options considered (independent traits vs. aggregate supertrait). +- The decision and rationale (aggregate supertrait — see Background above). +- The known constraint: trait-object upcasting from `dyn Database` to a narrow + `dyn XxxStore` requires Rust ≥ 1.76; the MSRV today is 1.72, so consumer wiring + stays as `Arc<Box<dyn Database>>` for now. + +Add a row to `docs/adrs/index.md`. + +### 2) Introduce the four narrow traits + +Create one file per trait. Each file contains only that trait's methods, moved verbatim +from `Database` (doc-comments included), plus `#[automock]` for mockall. + +**`databases/schema.rs`** — `SchemaMigrator`: + +```rust +#[automock] +pub trait SchemaMigrator: Sync + Send { + fn create_database_tables(&self) -> Result<(), Error>; + fn drop_database_tables(&self) -> Result<(), Error>; +} +``` + +**`databases/torrent_metrics.rs`** — `TorrentMetricsStore`: + +```rust +#[automock] +pub trait TorrentMetricsStore: Sync + Send { + fn load_all_torrents_downloads(&self) -> Result<NumberOfDownloadsBTreeMap, Error>; + fn load_torrent_downloads(&self, info_hash: &InfoHash) -> Result<Option<NumberOfDownloads>, Error>; + fn save_torrent_downloads(&self, info_hash: &InfoHash, downloaded: NumberOfDownloads) -> Result<(), Error>; + fn increase_downloads_for_torrent(&self, info_hash: &InfoHash) -> Result<(), Error>; + fn load_global_downloads(&self) -> Result<Option<NumberOfDownloads>, Error>; + fn save_global_downloads(&self, downloaded: NumberOfDownloads) -> Result<(), Error>; + fn increase_global_downloads(&self) -> Result<(), Error>; +} +``` + +**`databases/whitelist.rs`** — `WhitelistStore`: + +```rust +#[automock] +pub trait WhitelistStore: Sync + Send { + fn load_whitelist(&self) -> Result<Vec<InfoHash>, Error>; + fn get_info_hash_from_whitelist(&self, info_hash: InfoHash) -> Result<Option<InfoHash>, Error>; + fn add_info_hash_to_whitelist(&self, info_hash: InfoHash) -> Result<usize, Error>; + fn remove_info_hash_from_whitelist(&self, info_hash: InfoHash) -> Result<usize, Error>; + fn is_info_hash_whitelisted(&self, info_hash: InfoHash) -> Result<bool, Error> { + Ok(self.get_info_hash_from_whitelist(info_hash)?.is_some()) + } +} +``` + +**`databases/auth_keys.rs`** — `AuthKeyStore`: + +```rust +#[automock] +pub trait AuthKeyStore: Sync + Send { + fn load_keys(&self) -> Result<Vec<authentication::PeerKey>, Error>; + fn get_key_from_keys(&self, key: &Key) -> Result<Option<authentication::PeerKey>, Error>; + fn add_key_to_keys(&self, auth_key: &authentication::PeerKey) -> Result<usize, Error>; + fn remove_key_from_keys(&self, key: &Key) -> Result<usize, Error>; +} +``` + +### 3) Introduce the `Database` aggregate trait + +Create `databases/database.rs`: + +```rust +use super::{AuthKeyStore, SchemaMigrator, TorrentMetricsStore, WhitelistStore}; + +/// The full driver contract. +/// +/// A new database driver must implement all four supertrait bounds. The blanket +/// impl below means that any type satisfying all four automatically satisfies +/// `Database` — no separate `impl Database for MyDriver {}` is needed. +/// +/// `Arc<Box<dyn Database>>` continues to be the wiring type used by driver +/// setup and consumer repositories. Direct use of the narrow traits as +/// dependency types will become practical once the MSRV reaches 1.76 +/// (trait-object upcasting). +pub trait Database: + Sync + Send + SchemaMigrator + TorrentMetricsStore + WhitelistStore + AuthKeyStore +{ +} + +impl<T> Database for T where + T: Sync + Send + SchemaMigrator + TorrentMetricsStore + WhitelistStore + AuthKeyStore +{ +} +``` + +Remove the `#[automock]` from the old `Database` trait definition — mocking now happens +through the four narrow traits. + +### 4) Update the drivers + +In `driver/sqlite.rs` and `driver/mysql.rs`: + +- Remove `impl Database for <Driver> { ... }` (the blanket impl replaces it). +- Add four separate `impl` blocks — one per narrow trait — containing the same method + bodies that were previously in the single `impl Database` block. +- No logic changes. This is a mechanical redistribution of existing code. + +Example structure after the change: + +```rust +impl SchemaMigrator for Sqlite { + fn create_database_tables(&self) -> Result<(), Error> { ... } + fn drop_database_tables(&self) -> Result<(), Error> { ... } +} + +impl TorrentMetricsStore for Sqlite { + fn load_all_torrents_downloads(&self) -> Result<NumberOfDownloadsBTreeMap, Error> { ... } + // ... remaining 6 methods +} + +impl WhitelistStore for Sqlite { + // ... 5 methods +} + +impl AuthKeyStore for Sqlite { + // ... 4 methods +} +``` + +If the driver file becomes unwieldy, the four `impl` blocks can be moved into a +`driver/sqlite/` submodule — but that is optional and not required by this subissue. + +### 5) Update `mod.rs` + +- Declare the four new submodules. +- Re-export the traits and the `MockXxx` types so existing `use +crate::databases::Database` imports continue to work. +- Remove the method bodies and imports that were previously inlined in `mod.rs`. + +After the change, `mod.rs` should be a thin index: + +```rust +pub mod auth_keys; +pub mod database; +pub mod driver; +pub mod error; +pub mod schema; +pub mod setup; +pub mod torrent_metrics; +pub mod whitelist; + +pub use auth_keys::{AuthKeyStore, MockAuthKeyStore}; +pub use database::Database; +pub use schema::{MockSchemaMigrator, SchemaMigrator}; +pub use torrent_metrics::{MockTorrentMetricsStore, TorrentMetricsStore}; +pub use whitelist::{MockWhitelistStore, WhitelistStore}; +``` + +## Out of Scope + +- Changing consumer wiring from `Arc<Box<dyn Database>>` to narrow trait objects. + That is blocked by the MSRV constraint and is deferred. +- Async trait methods. That is subissue #1525-05. +- Schema migrations. That is subissue #1525-06. +- PostgreSQL support. That is subissue #1525-08. + +## Acceptance Criteria + +- [ ] ADR is written and added to `docs/adrs/index.md`. +- [ ] Four narrow traits exist in separate files under `databases/`. +- [ ] `Database` is an empty aggregate supertrait with a blanket impl. +- [ ] Both drivers (`Sqlite`, `Mysql`) compile through the blanket impl with no manual + `impl Database for <Driver>` block. +- [ ] No existing consumer file (`persisted.rs`, `downloads.rs`, etc.) is changed. +- [ ] `#[automock]` is on the four narrow traits; `MockDatabase` is removed. +- [ ] No behavior change — existing tests pass without modification. +- [ ] Persistence benchmarking (see subissue #1525-03) shows no regression against the + committed baseline. +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. + +## References + +- EPIC: #1525 +- Reference PR: #1695 +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- `packages/tracker-core/src/databases/mod.rs` — current monolithic `Database` trait +- `packages/tracker-core/src/whitelist/repository/persisted.rs` — example consumer +- `packages/tracker-core/src/statistics/persisted/downloads.rs` — example consumer +- `packages/tracker-core/src/authentication/key/repository/persisted.rs` — example consumer diff --git a/docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md b/docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md new file mode 100644 index 000000000..5b49a72cb --- /dev/null +++ b/docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md @@ -0,0 +1,280 @@ +# Subissue Draft for #1525-05: Migrate SQLite and MySQL Drivers to sqlx + +## Goal + +Move the existing SQL backends to a shared async `sqlx` substrate before adding PostgreSQL. + +## Why + +PostgreSQL should not be added as a special case. The existing SQL backends need to follow the same +async persistence model first so PostgreSQL can land on a common foundation. + +## Proposed Branch + +- `1525-05-migrate-sqlite-and-mysql-to-sqlx` + +## Background + +### Starting point + +By the time this subissue is implemented, subissue `1525-04` will have split the monolithic +`Database` trait into four narrow sync traits (`SchemaMigrator`, `TorrentMetricsStore`, +`WhitelistStore`, `AuthKeyStore`) plus a `Database` aggregate supertrait with a blanket impl. +Consumers still hold `Arc<Box<dyn Database>>`. + +The existing drivers (`Sqlite` in `driver/sqlite.rs`, `Mysql` in `driver/mysql.rs`) use +synchronous connection pools (`r2d2_sqlite`/`r2d2` for SQLite, the `mysql` crate for MySQL). +`build()` in `driver/mod.rs` calls `create_database_tables()` eagerly on startup. + +### Migration strategy: green parallel → single switch commit + +Rewriting both drivers at once while simultaneously making all four traits async would keep the +branch in a broken ("red") state for an extended period. Instead, this subissue uses a +**green parallel approach**: + +1. Build the async infrastructure and new driver implementations alongside the existing sync code + (Tasks 1–3). The branch compiles and all tests pass throughout these tasks. +2. Wire everything up and remove the old code in a single focused switch commit (Task 4). The + branch is briefly in a red state only during this commit. + +The technique is to put the async traits and new drivers in a temporary `databases/sqlx/` +submodule during Tasks 1–3. Task 4 moves them into place, updates consumers, and removes the sync +code. + +### What changes in the drivers + +The current drivers use blocking I/O and create the schema eagerly on construction. The new +`sqlx`-backed drivers: + +- Use `SqlitePool` / `MySqlPool` with lazy `connect_lazy_with()`. +- Manage the schema with raw `sqlx::query()` DDL statements (`CREATE TABLE IF NOT EXISTS ...`), + exactly mirroring what the current sync drivers do. `sqlx::migrate!()` and migration files are + **not** introduced here — that is subissue `1525-06`. +- Run `create_database_tables()` lazily the first time any operation is called, protected by an + `AtomicBool` + `Mutex` double-checked latch (`ensure_schema()`). +- All trait methods become `async fn` (via `async_trait`). + +## Tasks + +### Task 1 — Add sqlx infrastructure (no behavior change, stays green) + +Add the async substrate without touching the existing drivers or traits. + +#### Dependencies + +In `packages/tracker-core/Cargo.toml`, add: + +```toml +async-trait = "..." +sqlx = { version = "...", features = ["sqlite", "mysql", "runtime-tokio-native-tls"] } +tokio = { version = "...", features = ["full"] } # if not already present with needed features +``` + +Keep `r2d2`, `r2d2_sqlite`, `rusqlite`, and the `mysql` crate — they are still needed by the old +drivers until Task 4. + +#### Error handling + +Update `databases/error.rs` so that `sqlx::Error` can be converted into the existing `Error` type. +Add the following constructor methods and their corresponding enum variants. Do not add +`Error::migration_error()` — that belongs to `1525-06`: + +- `Error::connection_error()` — wraps connection failures (`sqlx::Error::Io`, pool errors, + etc.). Introduce the `ConnectionError` variant. +- `Error::invalid_query()` — wraps type-decoding and encoding failures. Used by + `decode_info_hash`, `decode_key`, `decode_valid_until`, and counter conversion helpers in + the async drivers. Also used by the `decode_counter`/`encode_counter` helpers introduced in + `1525-07` — introduce the variant here so `1525-07` requires no additional `error.rs` + changes. Introduce the `InvalidQuery` variant. +- `Error::query_returned_no_rows()` — for `sqlx::Error::RowNotFound`. Introduce the + `QueryReturnedNoRows` variant. +- `From<(sqlx::Error, Driver)>` — maps `sqlx::Error` variants to `ConnectionError`, + `QueryReturnedNoRows`, or `InvalidQuery` based on error kind (see reference `error.rs`). + +Do not change existing variants. + +**Outcome**: `cargo test --workspace --all-targets` still passes. No behavior change. + +### Task 2 — Implement async SQLite driver (stays green) + +Create a new async SQLite driver in a parallel `databases/sqlx/` submodule without touching the +existing `databases/driver/sqlite.rs`. + +#### New files + +```text +packages/tracker-core/src/databases/sqlx/mod.rs ← async trait definitions + AsyncDatabase aggregate +packages/tracker-core/src/databases/sqlx/sqlite.rs ← SqliteSqlx struct +``` + +#### Async trait definitions (`databases/sqlx/mod.rs`) + +Define async versions of the four narrow traits. Use `async_trait` for object safety: + +```rust +use async_trait::async_trait; + +#[async_trait] +pub trait AsyncSchemaMigrator: Send + Sync { + async fn create_database_tables(&self) -> Result<(), Error>; + async fn drop_database_tables(&self) -> Result<(), Error>; +} + +// ... AsyncTorrentMetricsStore, AsyncWhitelistStore, AsyncAuthKeyStore (same method +// signatures as their sync counterparts but with async fn) + +pub trait AsyncDatabase: + AsyncSchemaMigrator + AsyncTorrentMetricsStore + AsyncWhitelistStore + AsyncAuthKeyStore +{ +} + +impl<T> AsyncDatabase for T where + T: AsyncSchemaMigrator + AsyncTorrentMetricsStore + AsyncWhitelistStore + AsyncAuthKeyStore +{ +} +``` + +#### `SqliteSqlx` struct (`databases/sqlx/sqlite.rs`) + +Mirrors the reference `Sqlite` in `driver/sqlite.rs` (PR branch): + +```rust +use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; +use sqlx::SqlitePool; +use std::sync::atomic::{AtomicBool, Ordering}; +use tokio::sync::Mutex; + +pub(crate) struct SqliteSqlx { + pool: SqlitePool, + schema_ready: AtomicBool, + schema_lock: Mutex<()>, +} +``` + +Implement `AsyncSchemaMigrator`, `AsyncTorrentMetricsStore`, `AsyncWhitelistStore`, and +`AsyncAuthKeyStore` for `SqliteSqlx`. All SQL queries use `sqlx::query(...)`. Schema +initialization in `create_database_tables()` executes raw `CREATE TABLE IF NOT EXISTS ...` +statements via `sqlx::query()` — no `sqlx::migrate!()` in this step. + +#### Tests + +Add an inline `#[cfg(test)]` module in `databases/sqlx/sqlite.rs`. Use the shared +`databases/driver/tests::run_tests()` helper (or a new async equivalent) to run all behavioral +tests against `SqliteSqlx`. Use `torrust_tracker_test_helpers::configuration::ephemeral_sqlite_database` +for the in-memory/temp-file path. + +**Outcome**: `cargo test --workspace --all-targets` still passes. Old sync `Sqlite` driver +untouched. + +### Task 3 — Implement async MySQL driver (stays green) + +Create `packages/tracker-core/src/databases/sqlx/mysql.rs` with a `MysqlSqlx` struct mirroring +the same structure as `SqliteSqlx` but using `MySqlPool`. Schema initialization uses raw +`sqlx::query()` DDL — no `sqlx::migrate!()` in this step. + +Implement the same four async traits. Add an inline `#[cfg(test)]` module that runs the shared +behavioral test suite against a real MySQL instance (via environment variable guard +`TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true`, consistent with existing MySQL test gating). + +**Outcome**: `cargo test --workspace --all-targets` still passes. Old sync `Mysql` driver +untouched. + +### Task 4 — Switch: replace sync traits with async, update consumers (brief red) + +This task is a single focused commit. Steps within the commit: + +1. **Rename async traits to canonical names**: rename `AsyncSchemaMigrator` → `SchemaMigrator`, + `AsyncTorrentMetricsStore` → `TorrentMetricsStore`, etc. in `databases/sqlx/mod.rs`. Rename + `AsyncDatabase` → `Database`. Move the trait definitions from `databases/sqlx/mod.rs` into + `databases/mod.rs` (replacing the sync trait definitions). Move the driver files into the + existing driver directory, overwriting the old sync drivers: + `databases/sqlx/sqlite.rs` → `databases/driver/sqlite.rs` and + `databases/sqlx/mysql.rs` → `databases/driver/mysql.rs`. Remove the now-empty + `databases/sqlx/` submodule. + +2. **Rename driver structs**: rename `SqliteSqlx` → `Sqlite`, `MysqlSqlx` → `Mysql`. + +3. **Clean up old driver module helpers**: remove the sync test helpers from + `databases/driver/mod.rs` that reference `Arc<Box<dyn Database>>` with sync methods; replace + with async equivalents. (The old sync driver files at `databases/driver/sqlite.rs` and + `databases/driver/mysql.rs` were already overwritten by the async drivers in step 1.) + +4. **Update `databases/driver/mod.rs` `build()`**: the function no longer calls + `create_database_tables()` eagerly (schema is now lazy). Update the return type if needed. + +5. **Update `databases/setup.rs`**: `initialize_database()` constructs the new async `Sqlite` or + `Mysql` and wraps in `Arc<Box<dyn Database>>` (type stays the same, traits are now async). + +6. **Add `.await` at all consumer call sites**: every location that called a `Database` method + synchronously now needs `.await`. The affected files are: + - `statistics/persisted/downloads.rs` (`DatabaseDownloadsMetricRepository`) + - `whitelist/repository/persisted.rs` (`DatabaseWhitelist`) + - `whitelist/setup.rs` + - `authentication/key/repository/persisted.rs` (`DatabaseKeyRepository`) + - `authentication/handler.rs` (test helpers) + - Any integration tests in `tests/` + +7. **Remove unused dependencies**: remove `r2d2`, `r2d2_sqlite`, `rusqlite`, and the `mysql` crate + from `tracker-core/Cargo.toml`. Run `cargo machete` to verify. + +8. **Update mock usage**: `#[automock]` on the narrow traits generates async mocks via `mockall`. + Note that `MockDatabase` was already removed in `1525-04` (the aggregate supertrait has no + methods). The actual breakage surface in this switch commit is the four narrow-trait mocks: + `MockSchemaMigrator`, `MockTorrentMetricsStore`, `MockWhitelistStore`, and `MockAuthKeyStore`. + Any tests written against the **sync** versions of these mocks (from `1525-04`) will fail to + compile after the switch because async `mockall` mocks use + `.returning(|| Box::pin(async { Ok(()) }))` rather than `.returning(|| Ok(()))`. Find and + update all such tests before declaring this task complete. + +**Outcome**: `cargo test --workspace --all-targets` passes. `linter all` exits `0`. Sync drivers +and all `r2d2`/`rusqlite`/`mysql` dependencies are gone. + +## Constraints + +- Do not add PostgreSQL in this step. +- Do not introduce `sqlx::migrate!()`, migration files, or the `sqlx` `macros` feature — those + are introduced in subissue `1525-06`. +- Do not change the SQL schema in this step (schema evolution is `1525-06`). +- Keep `Arc<Box<dyn Database>>` as the consumer-facing type; do not introduce the `Persistence` + struct from the reference implementation (that is a separate concern). +- The lazy `ensure_schema()` latch must be correct under concurrent async access: use + `AtomicBool` (Acquire/Release) + `Mutex` double-checked pattern as in the reference. + +## Acceptance Criteria + +- [ ] SQLite and MySQL drivers use `sqlx` with async trait methods. +- [ ] Schema initialization is lazy (`ensure_schema()` pattern) — no eager call in `build()`. +- [ ] Schema management uses raw `sqlx::query()` DDL; `sqlx::migrate!()` is not used. +- [ ] `r2d2`, `r2d2_sqlite`, `rusqlite`, and the `mysql` crate are removed from + `tracker-core/Cargo.toml`. +- [ ] Existing behavior is preserved end-to-end. +- [ ] The branch compiles and all tests pass after each of Tasks 1–3 individually (verified by CI + or manual `cargo test` run after each task). +- [ ] Persistence benchmarking (see subissue `1525-03`) shows no regression against the committed + baseline. +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. +- [ ] `cargo machete` reports no unused dependencies. + +## Out of Scope + +- PostgreSQL driver — that is subissue `1525-08`. +- `sqlx::migrate!()` and migration files — that is subissue `1525-06`. +- `async_trait` removal — the `async_trait` crate is required at MSRV 1.72 because + async-fn-in-traits was stabilized in Rust 1.75. When the MSRV is raised to 1.75+, remove + `async_trait` and replace `#[async_trait]` attribute usage with native async trait syntax. + Track this as a follow-up when the MSRV is next bumped. + +## References + +- EPIC: `#1525` +- Subissue `1525-04`: `docs/issues/1525-04-split-persistence-traits.md` — must be completed first +- Subissue `1525-03`: `docs/issues/1525-03-persistence-benchmarking.md` — benchmark baseline +- Reference PR: `#1695` +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference files (async driver implementations — note: the reference uses `sqlx::migrate!()` + which is not adopted in this step; use raw DDL instead): + - `packages/tracker-core/src/databases/driver/sqlite.rs` + - `packages/tracker-core/src/databases/driver/mysql.rs` + - `packages/tracker-core/src/databases/driver/mod.rs` diff --git a/docs/issues/1525-06-introduce-schema-migrations.md b/docs/issues/1525-06-introduce-schema-migrations.md new file mode 100644 index 000000000..c2129b426 --- /dev/null +++ b/docs/issues/1525-06-introduce-schema-migrations.md @@ -0,0 +1,429 @@ +# Subissue Draft for #1525-06: Introduce Schema Migrations + +## Goal + +Replace the raw DDL calls in the async drivers with `sqlx`'s versioned migration framework, +making schema evolution explicit, reproducible, and aligned across all SQL backends. + +## Why + +After subissue `1525-05` the drivers still manage their schema through hand-written +`CREATE TABLE IF NOT EXISTS ...` statements executed by `create_database_tables()`. That approach +has no history, no ordering guarantees, and no way to apply incremental schema changes safely to +an existing database. `sqlx::migrate!()` gives us versioned SQL files, automatic up-migration on +startup, and a `_sqlx_migrations` tracking table — a foundation required before PostgreSQL can +be added (subissue `1525-08`). + +## Proposed Branch + +- `1525-06-introduce-schema-migrations` + +## Background + +### Starting point + +By the time this subissue is implemented, subissue `1525-05` will have delivered async SQLite +and MySQL drivers backed by `sqlx`. Each driver has an `ensure_schema()` latch that calls +`create_database_tables()` lazily. That method currently issues raw `sqlx::query()` DDL. This +subissue replaces that raw DDL path with `sqlx::migrate!()`. + +There are already 3 migration files under `packages/tracker-core/migrations/` (both `sqlite/` +and `mysql/` subdirectories) that capture the schema history: + +```text +20240730183000_torrust_tracker_create_all_tables.sql +20240730183500_torrust_tracker_keys_valid_until_nullable.sql +20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql +``` + +These files were written for users to run manually. The tracker has never executed them +automatically. This subissue is the first time they are wired into the application startup path. + +### Current code behavior + +The current `create_database_tables()` method issues `CREATE TABLE IF NOT EXISTS` for all four +tables (`whitelist`, `torrents`, `torrent_aggregate_metrics`, `keys`) using hardcoded DDL that +already reflects the final schema state (nullable `valid_until`, all four tables present). The +current `drop_database_tables()` drops `whitelist`, `torrents`, and `keys` but **not** +`torrent_aggregate_metrics`, which leaks across test drop/create cycles. + +This gives two distinct behaviors today: + +- **New (empty) database**: all four tables are created in the final schema state — equivalent + to having run all three migrations in sequence. The database is immediately usable. +- **Existing database (no `_sqlx_migrations` table)**: `IF NOT EXISTS` silently skips tables + that already exist. Migration 2's `ALTER TABLE` (making `valid_until` nullable) never runs, + so an old `keys` table with `valid_until NOT NULL` stays broken. Migration 3's + `torrent_aggregate_metrics` table is created if absent (it did not exist before migration 3). + The user is expected to run the missing migrations manually, as documented in + `packages/tracker-core/migrations/README.md`. + +### How sqlx migrations work + +`sqlx::migrate!("path/to/migrations")` is a compile-time macro that embeds all `.sql` files +found under the given directory into the binary. At runtime, calling `MIGRATOR.run(&pool)` +applies any unapplied migrations in timestamp order and records them in the `_sqlx_migrations` +tracking table. Each migration is applied exactly once; on subsequent runs its checksum is +verified but it is not re-applied. Migrations are irreversible by default (no down migrations). + +The `macros` feature of `sqlx` is required for the `sqlx::migrate!()` macro. + +Because the migration files are embedded at compile time, the running binary carries all +migrations and does not need the `.sql` files on disk at runtime. No special deployment +packaging is required beyond distributing the binary. + +### Migration file layout + +```text +packages/tracker-core/migrations/ + sqlite/ + 20240730183000_torrust_tracker_create_all_tables.sql + 20240730183500_torrust_tracker_keys_valid_until_nullable.sql + 20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql + mysql/ + 20240730183000_torrust_tracker_create_all_tables.sql + 20240730183500_torrust_tracker_keys_valid_until_nullable.sql + 20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql + postgresql/ ← added in subissue 1525-08; see "PostgreSQL migration alignment" below + ... +``` + +Each backend has its own directory because SQL dialects differ. + +### History-alignment pattern + +All backends must have the **same set of migration filenames** with the same timestamps. When a +schema change is not needed for a specific backend (e.g., a column-type widening that the +backend's native type system already handles), the migration file still exists for that backend +but contains only a comment: + +```sql +-- This migration is intentionally a no-op for this backend. +-- The migration file exists to keep the version history aligned +-- with the other backends. +``` + +This keeps the `_sqlx_migrations` version history identical across backends, which simplifies +reasoning about compatibility and avoids gaps in the timestamp sequence. + +### PostgreSQL migration alignment + +When subissue `1525-08` adds the PostgreSQL driver, its migration directory must contain the +**same set of migration filenames** as SQLite and MySQL, starting from migration 1 — treating +PostgreSQL as if it existed in the project from the beginning. This keeps the +`_sqlx_migrations` version history identical across all three backends. + +Concretely, PostgreSQL's migration 1 creates the original schema (same initial table definitions +as SQLite and MySQL migration 1), and the subsequent migrations apply the same schema changes in +order. Any migration that is a no-op for PostgreSQL follows the history-alignment pattern +(comment-only file) rather than being omitted. + +This means no additional "catch-up" migration is needed when PostgreSQL is added: the full +history starts from migration 1, identical to the other backends. + +### Legacy upgrade path + +When a v4 tracker starts against a database that was managed by an older tracker version, the +`_sqlx_migrations` table will not yet exist. Calling `MIGRATOR.run(&pool)` blindly on such a +database would try to re-apply migration 1 (`CREATE TABLE IF NOT EXISTS ...`) which is harmless +for `whitelist` and `torrents`, but migration 2's `ALTER TABLE` would fail because the +columns it targets are already in their expected state (on a fully-updated old schema) or in an +inconsistent state (on a partially-updated one). + +**Decision: legacy bootstrap with a v4 upgrade pre-condition.** + +The v4 changelog requires that users running an older tracker must apply all three existing +manual migrations before upgrading to v4. Once that pre-condition is met, the driver can +safely detect the legacy state and bootstrap the tracking table automatically: + +1. If `_sqlx_migrations` does **not** exist and the schema tables (`whitelist`, `torrents`, + `keys`, `torrent_aggregate_metrics`) do exist → **legacy bootstrap path**: + - Create the `_sqlx_migrations` table (via `MIGRATOR.ensure_migrations_table(&pool)`). + - Insert fake-applied rows for the three pre-existing migrations (correct versions and + checksums from the embedded `MIGRATOR`), marking them as already executed. + - Call `MIGRATOR.run(&pool)` to apply any migrations added after those three. +2. If `_sqlx_migrations` exists → **normal path**: call `MIGRATOR.run(&pool)` directly; sqlx + skips already-applied migrations. +3. If no tables exist at all → **fresh database path**: `MIGRATOR.run(&pool)` creates + `_sqlx_migrations` and applies all migrations from scratch. + +This logic lives in a helper function called before `MIGRATOR.run(&pool)` inside +`create_database_tables()`. + +### Effect on `ensure_schema()` / `create_database_tables()` + +After this subissue, `SchemaMigrator::create_database_tables()` calls the legacy-bootstrap +helper and then `MIGRATOR.run(&pool)` instead of issuing raw DDL. `drop_database_tables()` +(used only in tests) must also drop the `_sqlx_migrations` and `torrent_aggregate_metrics` +tables (fixing the pre-existing omission) so that the drop/create cycle used in the test suite +works correctly. + +## Tasks + +### Task 1 — Verify existing migration files + +The three migration files already exist under `packages/tracker-core/migrations/`. Verify that +their SQL content is correct and consistent with the current schema produced by the hardcoded +DDL in `1525-05`. Do not change existing file timestamps or names. Fix content only if a +discrepancy is found. + +**Outcome**: all three migration files are verified correct; nothing else changes yet. + +### Task 2 — Enable `sqlx` `macros` feature and add `MIGRATOR` statics + +In `packages/tracker-core/Cargo.toml`, add the `macros` feature to the existing `sqlx` +dependency: + +```toml +sqlx = { version = "...", features = ["sqlite", "mysql", "macros", "runtime-tokio-native-tls"] } +``` + +In each driver file add a static migrator: + +```rust +use sqlx::migrate::Migrator; + +// SQLite driver +static MIGRATOR: Migrator = sqlx::migrate!("migrations/sqlite"); + +// MySQL driver +static MIGRATOR: Migrator = sqlx::migrate!("migrations/mysql"); +``` + +Add `Error::migration_error()` to `databases/error.rs` to wrap `sqlx::migrate::MigrateError`. + +**Outcome**: project compiles with migration statics defined but not yet called. + +### Task 3 — Wire migrations into `create_database_tables()` and `drop_database_tables()` + +#### Legacy bootstrap helper + +Add a private async helper function `bootstrap_legacy_schema` to each driver. This function +detects whether the database is in the legacy state (user-managed schema, no +`_sqlx_migrations` table) and, if so, fake-applies the three pre-existing migrations so that +`MIGRATOR.run()` can continue with only the new ones: + +```rust +async fn bootstrap_legacy_schema(pool: &Pool) -> Result<(), Error> { + // Check whether _sqlx_migrations already exists. + let migrations_table_exists: bool = /* backend-appropriate query */; + if migrations_table_exists { + return Ok(()); // normal path — nothing to do here + } + + // Check whether the legacy tables exist (whitelist is a reliable sentinel). + let legacy_tables_exist: bool = /* backend-appropriate query */; + if !legacy_tables_exist { + return Ok(()); // fresh database — MIGRATOR.run() will handle it + } + + // PRECONDITION GUARD: before fake-applying, verify that migration 2 (nullable + // valid_until) and migration 3 (torrent_aggregate_metrics table) were applied. + // If not, return a descriptive error rather than silently bootstrapping a broken schema. + // SQLite: use `PRAGMA table_info(keys)` and `sqlite_master`. + // MySQL: use `information_schema.columns` and `information_schema.tables`. + let migration_2_applied: bool = /* check keys.valid_until is nullable */; + let migration_3_applied: bool = /* check torrent_aggregate_metrics table exists */; + if !migration_2_applied || !migration_3_applied { + return Err(Error::migration_error( + DRIVER, + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Legacy database is not fully migrated. Apply all three manual migrations \ + listed in packages/tracker-core/migrations/README.md before upgrading to v4.", + ), + )); + } + + // PRECONDITION: all three manual migrations have been verified as applied: + // (1) whitelist/torrents/keys tables exist (whitelist sentinel check above) + // (2) keys.valid_until is nullable (verified above) + // (3) torrent_aggregate_metrics table exists (verified above) + // The v4 upgrade guide requires the user to have applied all three manual migrations + // before upgrading to v4. + MIGRATOR + .ensure_migrations_table(pool) + .await + .map_err(|e| Error::migration_error(DRIVER, e))?; + for migration in MIGRATOR.iter() { + if migration.version <= 20_250_527_093_000 { + // sqlx 0.8 does not expose a public `apply_fake()` API on `Migrator`. + // Fake-apply by inserting directly into `_sqlx_migrations`. The `checksum` + // field MUST equal the value embedded in the compiled binary (from + // `migration.checksum`) so that subsequent `MIGRATOR.run()` calls pass the + // checksum-verification step and do not raise a mismatch error. + // + // The INSERT uses `?` placeholders, valid for both SQLite and MySQL (this + // function lives in the driver-specific file, not in shared code). + sqlx::query( + "INSERT INTO _sqlx_migrations \ + (version, description, installed_on, success, checksum, execution_time) \ + VALUES (?, ?, CURRENT_TIMESTAMP, TRUE, ?, 0)", + ) + .bind(migration.version) + .bind(migration.description.as_ref()) + .bind(migration.checksum.as_ref()) + .execute(pool) + .await + .map_err(|e| Error::migration_error(DRIVER, e))?; + } + } + Ok(()) +} +``` + +#### Updated `create_database_tables()` + +```rust +async fn create_database_tables(&self) -> Result<(), Error> { + bootstrap_legacy_schema(&self.pool).await?; + MIGRATOR.run(&self.pool).await.map_err(|e| Error::migration_error(DRIVER, e))?;; + Ok(()) +} +``` + +#### Updated `drop_database_tables()` + +Fix the pre-existing omission: drop `torrent_aggregate_metrics` and `_sqlx_migrations` in +addition to the existing drops so that the test setup cycle (drop → create) works correctly. + +Use `DROP TABLE IF EXISTS` for all five drops. This matches the reference implementation and +is the safer choice for test teardown (avoids errors on a partially torn-down database). + +```rust +// Example using DROP TABLE IF EXISTS for all five drops: +sqlx::query("DROP TABLE IF EXISTS _sqlx_migrations").execute(&self.pool).await...?; +sqlx::query("DROP TABLE IF EXISTS torrent_aggregate_metrics").execute(&self.pool).await...?; +sqlx::query("DROP TABLE IF EXISTS whitelist").execute(&self.pool).await...?; +sqlx::query("DROP TABLE IF EXISTS torrents").execute(&self.pool).await...?; +sqlx::query("DROP TABLE IF EXISTS keys").execute(&self.pool).await...?; +``` + +#### Legacy bootstrap precondition guard + +The `bootstrap_legacy_schema()` helper must verify the critical schema elements before +fake-applying migrations. If any element is absent, it must return an error rather than +silently bootstrapping a broken schema. Add the precondition checks described in the code +block above (migration 2 nullable check and migration 3 table existence check) and document +the verified state with a comment: + +```rust +// PRECONDITION: all three manual migrations have been verified as applied: +// (1) whitelist/torrents/keys tables exist (whitelist sentinel check above) +// (2) keys.valid_until is nullable (verified above) +// (3) torrent_aggregate_metrics table exists (verified above) +// The v4 upgrade guide requires the user to have applied all three manual migrations +// before upgrading to v4. +``` + +#### Update `migrations/README.md` + +Update `packages/tracker-core/migrations/README.md` to replace the stale content (currently: +"We don't support automatic migrations yet") with accurate documentation covering: + +- Migrations are now applied automatically on startup via `sqlx::migrate!()`. +- The `_sqlx_migrations` table tracks which migrations have run. +- To add a new migration: create a `.sql` file with the next timestamp in all applicable backend + directories, following the history-alignment pattern. +- v4 upgrade requirement: users on a pre-v4 tracker must apply all three manual migrations before + upgrading to v4. The automatic bootstrap handles the rest. +- **Migration file immutability**: once a migration file has been deployed, it must never be + modified. `sqlx` records each migration's checksum in `_sqlx_migrations`; editing a committed + migration file causes a checksum-mismatch error on the next startup for any database that has + already applied that migration. + +The `ensure_schema()` latch remains in place — it now guards the +`bootstrap_legacy_schema()` + `MIGRATOR.run()` sequence. + +**Outcome**: `cargo test --workspace --all-targets` passes. Schema is owned by migration files. +The README accurately reflects the new automatic migration behavior. + +### Task 4 — Validate migration behavior + +Add or extend tests that verify: + +- **Fresh database**: a single `create_database_tables()` call runs all migrations and + leaves the database in the correct final schema state. +- **Idempotency**: calling `create_database_tables()` a second time on an already-migrated + database is a no-op (all migrations already recorded in `_sqlx_migrations`). +- **Drop/create cycle**: `drop_database_tables()` followed by `create_database_tables()` + produces a clean schema (all tables including `_sqlx_migrations` and + `torrent_aggregate_metrics` are dropped and recreated). +- **Legacy bootstrap**: a database that has the pre-existing three tables (created without + `_sqlx_migrations`) is correctly bootstrapped — `_sqlx_migrations` is created, the three + migrations are marked fake-applied, and any new migrations are applied. +- **Partial-migration guard**: a database that has the schema tables but is missing + `torrent_aggregate_metrics` (migration 3 not applied) must cause `bootstrap_legacy_schema()` + to return an error, not silently proceed. + +These tests can live alongside the existing behavioral tests in the driver `#[cfg(test)]` +modules. + +## Out of Scope + +- PostgreSQL migration files — those are added in subissue `1525-08`. The + [PostgreSQL migration alignment](#postgresql-migration-alignment) section above specifies + the history-alignment requirement: PostgreSQL must start from migration 1 (not a catch-up + migration) to keep version history identical across all backends. +- Down migrations (rollback) — not needed at this stage. +- Handling legacy databases where not all three manual migrations were applied — the v4 + changelog must state that all three migrations must be applied before upgrading to v4. + The legacy bootstrap path verifies this precondition and returns an error if it is not met + (see the precondition guard above). +- **Migration file integrity check in CI** — `sqlx migrate check` (or an equivalent + step that connects to a fresh database and verifies checksums) can detect if a deployed + migration file has been edited after deployment. This requires a live database in CI and + is a follow-up improvement. It is out of scope here but worth adding once a database + service is reliably available in the CI pipeline (e.g., after subissue `1525-08` wires in + the PostgreSQL service). + +## Acceptance Criteria + +- [ ] The three existing migration files under `migrations/sqlite/` and `migrations/mysql/` are + confirmed correct and match the final schema produced by the hardcoded DDL in `1525-05`. +- [ ] `sqlx::migrate!()` (`macros` feature) is used in both drivers; no raw DDL remains in + `create_database_tables()`. +- [ ] `drop_database_tables()` drops `_sqlx_migrations` **and** `torrent_aggregate_metrics` + (fixing the pre-existing omission) so the test cycle works. All five drops use + `DROP TABLE IF EXISTS`. +- [ ] `bootstrap_legacy_schema()` verifies that migrations 2 and 3 were applied before + fake-applying, and returns a descriptive error if the precondition is not met. +- [ ] `Error::migration_error()` wraps `sqlx::migrate::MigrateError`. +- [ ] `packages/tracker-core/migrations/README.md` is updated to document automatic migration + behavior and the v4 upgrade requirement. +- [ ] Guidance for `1525-08`: PostgreSQL migration files start from migration 1 following the + history-alignment pattern, with the same filenames/timestamps as SQLite and MySQL. +- [ ] Legacy bootstrap: a database with the pre-existing tables but no `_sqlx_migrations` is + correctly detected; the three pre-existing migrations are fake-applied; new migrations + run normally. +- [ ] Fresh database: `create_database_tables()` runs all migrations from scratch via + `MIGRATOR.run()`. +- [ ] Migration idempotency is verified by tests (second call is a no-op). +- [ ] Drop/create cycle is verified by tests (all tables cleaned up and recreated). +- [ ] Legacy bootstrap scenario is verified by a test (fully-migrated legacy database is + bootstrapped correctly). +- [ ] Partial-migration guard is verified by a test (database missing `torrent_aggregate_metrics` + causes an error rather than silent bootstrap). +- [ ] Existing behavioral tests continue to pass. +- [ ] The v4 changelog or upgrade guide documents the pre-upgrade requirement: apply all three + manual migrations before upgrading to v4. +- [ ] Persistence benchmarking (see subissue `1525-03`) shows no regression against the committed + baseline. +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. + +## References + +- EPIC: `#1525` +- Subissue `1525-05`: `docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md` — must be + completed first +- Subissue `1525-03`: `docs/issues/1525-03-persistence-benchmarking.md` — benchmark baseline +- Reference PR: `#1695` +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference files (migration files and driver wiring): + - `packages/tracker-core/migrations/sqlite/` + - `packages/tracker-core/migrations/mysql/` + - `packages/tracker-core/src/databases/driver/sqlite.rs` + - `packages/tracker-core/src/databases/driver/mysql.rs` +- Existing migration README: `packages/tracker-core/migrations/README.md` diff --git a/docs/issues/1525-07-align-rust-and-db-types.md b/docs/issues/1525-07-align-rust-and-db-types.md new file mode 100644 index 000000000..fe389354c --- /dev/null +++ b/docs/issues/1525-07-align-rust-and-db-types.md @@ -0,0 +1,228 @@ +# Subissue 1525-07: Align Rust and Database Types + +## Goal + +Widen the download-counter type in Rust from `u32` to `u64` and widen the corresponding +database columns from `INTEGER` (32-bit, MySQL) to `BIGINT` (64-bit), delivered as a versioned +`sqlx` migration so the change is explicit, testable, and reversible. + +## Background + +### Current state + +By the time this subissue is implemented, subissue `1525-06` will have wired `sqlx::migrate!()` +into both drivers. The schema at that point contains: + +- `torrents.completed` — `INTEGER` in MySQL (32-bit signed, max ≈ 2.1 billion), `INTEGER` in + SQLite (storage is already 64-bit for any integer value). +- `torrent_aggregate_metrics.value` — same types as above. + +The Rust type alias is `NumberOfDownloads = u32` in +`packages/primitives/src/lib.rs`. The `SwarmMetadata.downloaded` field also uses this type. +The drivers read the column as `i64` (sqlx always returns integer columns as `i64`) and +immediately narrow-cast to `u32`. + +### Why this is a problem + +The MySQL `INT` column type is **signed 32-bit** (max 2,147,483,647). Writing a `u32` value +above that limit silently overflows or errors. Practically, the counter saturates at the same +point as the UDP scrape wire format (`completed` is `i32` in BEP 15), but the correct fix is +to widen the storage type rather than rely on implicit saturation in the driver. + +`u32::MAX` (4,294,967,295) is already higher than the `i32::MAX` wire limit, so protocol +saturation happens before storage overflow today. However, aligning storage to `BIGINT` and the +Rust type to `u64` makes the storage contract explicit and decoupled from any particular +protocol encoding. Future protocol changes or a direct-database query tool cannot accidentally +exceed a silently-constrained column. + +**Protocol encoding** (read-only, no changes needed in this subissue): + +- UDP scrape response (`i32` wire field): the existing conversion from `NumberOfDownloads` to + `i32` already saturates at `i32::MAX`. This remains unchanged. +- HTTP scrape response (bencoded `i64`): `bencode_download_count()` saturates at `i64::MAX`. + This remains unchanged. + +### Why migrations first (1525-06 before 1525-07) + +The column-widening change must be delivered as a versioned migration rather than an ad hoc DDL +update. Having the migration framework from `1525-06` in place ensures the change is tracked in +`_sqlx_migrations`, tested like any other migration, and can be reasoned about in production +upgrade scenarios. + +## Proposed Branch + +- `1525-07-align-rust-and-db-types` + +## What Changes + +### Migration files + +Add the fourth migration to both existing backends: + +```text +packages/tracker-core/migrations/sqlite/20260409120000_torrust_tracker_widen_download_counters.sql +packages/tracker-core/migrations/mysql/20260409120000_torrust_tracker_widen_download_counters.sql +``` + +**SQLite** — no-op (SQLite already stores any `INTEGER` value as a 64-bit signed integer): + +```sql +-- SQLite stores INTEGER values as signed 64-bit integers already. +-- This migration is intentionally a no-op so the migration history stays +-- aligned with the MySQL backend. +``` + +**MySQL** — widen both download-counter columns: + +```sql +ALTER TABLE torrents + MODIFY completed BIGINT NOT NULL DEFAULT 0; + +ALTER TABLE torrent_aggregate_metrics + MODIFY value BIGINT NOT NULL DEFAULT 0; +``` + +PostgreSQL migration files are not created here. They will be added in subissue `1525-08` when +the PostgreSQL driver is introduced. Following the +[history-alignment pattern](1525-06-introduce-schema-migrations.md#history-alignment-pattern) +established in `1525-06`, subissue `1525-08` creates **all four** migration files for +PostgreSQL starting from migration 1. PostgreSQL's migration 1 creates the columns as +`INTEGER` (matching the original schema from the other backends), and migration 4 widens them +to `BIGINT` using PostgreSQL-specific `ALTER COLUMN ... TYPE BIGINT` syntax. Migration 4 is +not a no-op for PostgreSQL. + +### Rust type changes + +**`packages/primitives/src/lib.rs`** — widen the type alias: + +```rust +// Before +pub type NumberOfDownloads = u32; + +// After +pub type NumberOfDownloads = u64; +``` + +**`packages/primitives/src/swarm_metadata.rs`** — `downloaded` field currently uses the bare +`u32`. Update it to use `NumberOfDownloads` explicitly: + +```rust +// Before +pub downloaded: u32, + +// After +pub downloaded: NumberOfDownloads, +``` + +Also update the `downloads()` method return type to `NumberOfDownloads`. + +### Driver conversion changes + +After `1525-05`, the sqlx drivers read counter columns as `i64`. With `NumberOfDownloads = u32` +the read path does `u32::try_from(i64_value)`. After this subissue it becomes +`u64::try_from(i64_value)`. + +Because the database column type is `BIGINT` (signed), the **write path** must also encode +`u64 → i64`. Values above `i64::MAX` (≈ 9.2 × 10¹⁸) cannot be stored and must return an +error rather than silently truncate. Add named helper methods to each driver to make the +conversion explicit and consistent: + +```rust +fn decode_counter(value: i64) -> Result<NumberOfDownloads, Error> { + u64::try_from(value).map_err(|err| Error::invalid_query(DRIVER, err)) +} + +fn encode_counter(value: NumberOfDownloads) -> Result<i64, Error> { + i64::try_from(value).map_err(|err| Error::invalid_query(DRIVER, err)) +} +``` + +Use these helpers in every place a counter column is read from or written to the database. + +### Cascade compilation fixes + +Widening `NumberOfDownloads` from `u32` to `u64` will produce compilation errors wherever the +old `u32` range was assumed. Fix all errors; do not add `as u32` casts or `allow` attributes +to suppress them. + +## Tasks + +### Task 1 — Add migration files + +Create the two new migration files listed above. Do not modify any existing migration file. + +**Outcome**: `packages/tracker-core/migrations/` has four files in each of `sqlite/` and +`mysql/`. The fourth file is verified by running the migration against a fresh test database +of each type. + +### Task 2 — Widen `NumberOfDownloads` and fix cascade + +Change `NumberOfDownloads = u32 → u64` in `packages/primitives/src/lib.rs` and update +`SwarmMetadata.downloaded` to use the alias. Fix all resulting compilation errors across the +workspace (driver conversion logic, scrape response encoding, announce handler arithmetic, +etc.). + +Add `decode_counter` / `encode_counter` helpers to both driver files as described above. + +**Outcome**: `cargo build --workspace` succeeds with no warnings or errors. + +### Task 3 — Validate migration and type alignment + +Add or extend tests that verify: + +- **MySQL migration**: running the migration on a database with the pre-migration `INT` column + produces a `BIGINT` column, and writing and reading a value larger than `2^31 − 1` round-trips + correctly. +- **SQLite no-op**: the migration applies cleanly (recorded in `_sqlx_migrations`) and the + column already accepts large values. +- **Boundary encode**: writing a `u64` counter value of exactly `i64::MAX` succeeds; writing + `i64::MAX + 1` returns an appropriate error rather than panicking or wrapping. + +These tests extend the existing driver `#[cfg(test)]` modules. + +**Outcome**: `cargo test --workspace --all-targets` passes. + +## Out of Scope + +- PostgreSQL migration files — added in subissue `1525-08`. +- Down migrations (rollback) — not needed at this stage. +- Trait splitting or other structural refactoring. +- Other numeric types beyond `NumberOfDownloads` / download counters. + +## Acceptance Criteria + +- [ ] `packages/tracker-core/migrations/sqlite/20260409120000_torrust_tracker_widen_download_counters.sql` + exists and is a comment-only no-op. +- [ ] `packages/tracker-core/migrations/mysql/20260409120000_torrust_tracker_widen_download_counters.sql` + exists and widens `torrents.completed` and `torrent_aggregate_metrics.value` to `BIGINT`. +- [ ] `NumberOfDownloads = u64` in `packages/primitives/src/lib.rs`. +- [ ] `SwarmMetadata.downloaded` uses `NumberOfDownloads`; bare `u32` is removed from that field. +- [ ] Both driver files use explicit `decode_counter` / `encode_counter` helpers for all + counter-column reads and writes. +- [ ] `encode_counter` returns an error (not a panic, not silent truncation) for values + above `i64::MAX`. +- [ ] A test verifies round-trip of a value larger than `u32::MAX` for each backend. +- [ ] A test verifies the encode error path for values above `i64::MAX`. +- [ ] No `as u32` casts or compiler-suppression attributes introduced by this subissue. +- [ ] Persistence benchmarking (see subissue `1525-03`) shows no regression against the + committed baseline. +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `linter all` exits with code `0`. + +## References + +- EPIC: `#1525` +- Subissue `1525-06`: `docs/issues/1525-06-introduce-schema-migrations.md` — must be completed + first (provides the migration framework) +- Subissue `1525-08`: `docs/issues/1525-08-add-postgresql-driver.md` — adds PostgreSQL + migration files including the history-aligned no-op for this migration +- Subissue `1525-03`: `docs/issues/1525-03-persistence-benchmarking.md` — benchmark baseline +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions (`docs/issues/1525-overhaul-persistence.md`) +- Reference files: + - `packages/tracker-core/migrations/sqlite/20260409120000_torrust_tracker_widen_download_counters.sql` + - `packages/tracker-core/migrations/mysql/20260409120000_torrust_tracker_widen_download_counters.sql` + - `packages/primitives/src/lib.rs` (type alias change) + - `packages/primitives/src/swarm_metadata.rs` (field type change) + - `packages/tracker-core/src/databases/driver/sqlite.rs` (decode/encode helpers) + - `packages/tracker-core/src/databases/driver/mysql.rs` (decode/encode helpers) diff --git a/docs/issues/1525-08-add-postgresql-driver.md b/docs/issues/1525-08-add-postgresql-driver.md new file mode 100644 index 000000000..7582f92ba --- /dev/null +++ b/docs/issues/1525-08-add-postgresql-driver.md @@ -0,0 +1,723 @@ +# Subissue 1525-08: Add PostgreSQL Driver + +## Goal + +Add PostgreSQL as a third production SQL backend by implementing an async `sqlx`-backed +driver, wiring it into the configuration and factory, creating all four migration files +(starting from migration 1, history-aligned with SQLite and MySQL), and extending the +existing QA harnesses so PostgreSQL receives the same test coverage as the other backends. + +## Why Last + +PostgreSQL is the feature goal of the EPIC, but adding it first would have meant building on +an ad hoc, sync, pre-migration foundation. By the time this subissue is implemented, the +persistence layer is async (`1525-05`), schema-managed (`1525-06`), and correctly typed +(`1525-07`). PostgreSQL can now land as a first-class backend with no special-casing. + +## Proposed Branch + +- `1525-08-add-postgresql-driver` + +## Background + +### Starting point + +By the time this subissue is implemented: + +- **1525-04** has split the monolithic `Database` trait into four narrow context traits + (`SchemaMigrator`, `TorrentMetricsStore`, `WhitelistStore`, `AuthKeyStore`) plus a blanket + `Database` aggregate supertrait. Both existing drivers (`Sqlite`, `Mysql`) satisfy `Database` + through the blanket impl. Consumers hold `Arc<Box<dyn Database>>`. + +- **1525-05** has moved SQLite and MySQL to async `sqlx` connection pools. `r2d2`, `r2d2_sqlite`, + `rusqlite`, and the `mysql` crate are gone. The `sqlx` dependency has `sqlite` and `mysql` + features but not yet `postgres`. + +- **1525-06** has replaced the raw DDL in `create_database_tables()` with `sqlx::migrate!()`. + Each driver has a `static MIGRATOR` pointing to its backend-specific migration directory and + a `bootstrap_legacy_schema()` helper for upgrading pre-v4 databases. Both backends have three + migration files. + +- **1525-07** has widened `NumberOfDownloads` from `u32` to `u64`, added a fourth migration to + SQLite and MySQL, and added `decode_counter`/`encode_counter` helpers to both drivers. The + migration file layout at the end of `1525-07` is: + + ```text + packages/tracker-core/migrations/ + sqlite/ + 20240730183000_torrust_tracker_create_all_tables.sql + 20240730183500_torrust_tracker_keys_valid_until_nullable.sql + 20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql + 20260409120000_torrust_tracker_widen_download_counters.sql + mysql/ + 20240730183000_torrust_tracker_create_all_tables.sql + 20240730183500_torrust_tracker_keys_valid_until_nullable.sql + 20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql + 20260409120000_torrust_tracker_widen_download_counters.sql + ``` + + No `postgresql/` directory exists yet. + +### Driver enum locations + +Two separate `Driver` enums exist and both must be extended: + +- **Configuration** — `packages/configuration/src/v2_0_0/database.rs`: user-facing config + file value. Holds `Sqlite3`, `MySQL`. Used by the tracker to select which driver to build. +- **Databases factory** — `packages/tracker-core/src/databases/driver/mod.rs`: internal + dispatch enum. Holds `Sqlite3`, `MySQL`. `build()` matches on this to construct the driver. + `databases/setup.rs` converts from the configuration enum to this internal enum. + +### No legacy bootstrap for PostgreSQL + +The `bootstrap_legacy_schema()` helper introduced in `1525-06` exists to upgrade databases +that were managed manually before v4. PostgreSQL was never supported before this subissue, so +no pre-existing PostgreSQL tracker databases exist. The PostgreSQL `create_database_tables()` +implementation skips the legacy bootstrap and calls `MIGRATOR.run()` directly. + +### Connection string format + +PostgreSQL uses the same `path` field as MySQL in the configuration — a single URL string: + +```toml +[core.database] +driver = "postgresql" +path = "postgresql://user:password@host:port/dbname" +``` + +The `mask_secrets()` function in the configuration package must be extended to parse and +redact the password from this URL, mirroring the existing MySQL URL masking logic. + +### Database pre-creation requirement + +Unlike SQLite (which creates its file on first connection), PostgreSQL requires the target +database to already exist before `sqlx` can connect. The `torrust_tracker` database referenced +in the connection URL must be created before the tracker starts: + +```sql +CREATE DATABASE torrust_tracker; +``` + +**Test containers**: the `PostgresConfiguration.database` field (`torrust_tracker_test` by +default) is passed as the `POSTGRES_DB` env var to the PostgreSQL container. The official +`postgres` Docker image creates this database automatically — no manual `CREATE DATABASE` +call is needed in test code. + +**Container config** (`tracker.container.postgresql.toml`): the URL points to +`postgresql://postgres:postgres@postgres:5432/torrust_tracker`. The accompanying compose file +or deployment guide must ensure the `torrust_tracker` database exists — either by setting +`POSTGRES_DB=torrust_tracker` on the PostgreSQL service, or by running a setup step before the +tracker starts. Without it, the tracker will exit on startup with a `sqlx` connection error +that does not clearly identify the missing database as the cause. + +## What Changes + +### Migration files + +Create a `postgresql/` directory under `packages/tracker-core/migrations/` with all four +migration files. The timestamps are shared with the SQLite and MySQL backends, keeping the +`_sqlx_migrations` version history identical across all three backends. Migration 4 is **not** +a no-op for PostgreSQL — PostgreSQL's migration 1 creates the columns as `INTEGER` (matching +the other backends at their migration-1 state), and migration 4 widens them to `BIGINT` using +PostgreSQL-specific `ALTER COLUMN` syntax. + +**`20240730183000_torrust_tracker_create_all_tables.sql`**: + +```sql +CREATE TABLE IF NOT EXISTS whitelist ( + id SERIAL PRIMARY KEY, + info_hash VARCHAR(40) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS torrents ( + id SERIAL PRIMARY KEY, + info_hash VARCHAR(40) NOT NULL UNIQUE, + completed INTEGER DEFAULT 0 NOT NULL +); + +CREATE TABLE IF NOT EXISTS keys ( + id SERIAL PRIMARY KEY, + key VARCHAR(32) NOT NULL UNIQUE, + valid_until BIGINT NOT NULL +); +``` + +PostgreSQL differences from MySQL and SQLite: `SERIAL` instead of `AUTO_INCREMENT` or +`INTEGER PRIMARY KEY AUTOINCREMENT`; no backtick quoting; parameter placeholders are `$1`, +`$2`, … in DML queries (not `?`). + +**`20240730183500_torrust_tracker_keys_valid_until_nullable.sql`**: + +```sql +ALTER TABLE keys ALTER COLUMN valid_until DROP NOT NULL; +``` + +**`20250527093000_torrust_tracker_new_torrent_aggregate_metrics_table.sql`**: + +```sql +CREATE TABLE IF NOT EXISTS torrent_aggregate_metrics ( + id SERIAL PRIMARY KEY, + metric_name VARCHAR(50) NOT NULL UNIQUE, + value INTEGER DEFAULT 0 NOT NULL +); +``` + +**`20260409120000_torrust_tracker_widen_download_counters.sql`**: + +```sql +ALTER TABLE torrents + ALTER COLUMN completed TYPE BIGINT, + ALTER COLUMN completed SET DEFAULT 0, + ALTER COLUMN completed SET NOT NULL; + +ALTER TABLE torrent_aggregate_metrics + ALTER COLUMN value TYPE BIGINT, + ALTER COLUMN value SET DEFAULT 0, + ALTER COLUMN value SET NOT NULL; +``` + +### Configuration package + +In `packages/configuration/src/v2_0_0/database.rs`: + +- Add `PostgreSQL` variant to the `Driver` enum: + + ```rust + #[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)] + #[serde(rename_all = "lowercase")] + pub enum Driver { + Sqlite3, + MySQL, + PostgreSQL, // new + } + ``` + +- Extend `mask_secrets()` to handle the PostgreSQL URL. MySQL and PostgreSQL both use a URL + `path`; the masking code can share a branch: + + ```rust + Driver::MySQL | Driver::PostgreSQL => { + let mut url = Url::parse(&self.path)?; + url.set_password(Some("***")).ok(); + self.path = url.to_string(); + } + ``` + +- Add a test: + + ```rust + fn it_should_allow_masking_the_postgresql_user_password() + ``` + +### `tracker-core` Cargo.toml + +Add `"postgres"` to the `sqlx` features list: + +```toml +sqlx = { version = "...", features = [ + "sqlite", "mysql", "postgres", "macros", "runtime-tokio-native-tls" +] } +``` + +### PostgreSQL driver + +New file: `packages/tracker-core/src/databases/driver/postgres.rs`. + +**Driver struct and constructor**: + +```rust +use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; +use sqlx::{ConnectOptions, PgPool, Row}; +use std::sync::atomic::{AtomicBool, Ordering}; +use tokio::sync::Mutex; + +const DRIVER: &str = "postgresql"; + +static MIGRATOR: Migrator = sqlx::migrate!("migrations/postgresql"); + +pub(crate) struct Postgres { + pool: PgPool, + schema_ready: AtomicBool, + schema_lock: Mutex<()>, +} + +impl Postgres { + pub fn new(db_path: &str) -> Result<Self, Error> { + let options = db_path + .parse::<PgConnectOptions>() + .map_err(|e| Error::connection_error(DRIVER, e))? + .disable_statement_logging(); + let pool = PgPoolOptions::new().connect_lazy_with(options); + Ok(Self { + pool, + schema_ready: AtomicBool::new(false), + schema_lock: Mutex::new(()), + }) + } +} +``` + +**Lazy migration latch** (same double-checked pattern as SQLite and MySQL): + +```rust +async fn ensure_schema(&self) -> Result<(), Error> { + if self.schema_ready.load(Ordering::Acquire) { + return Ok(()); + } + let _guard = self.schema_lock.lock().await; + if self.schema_ready.load(Ordering::Acquire) { + return Ok(()); + } + self.create_database_tables().await?; + self.schema_ready.store(true, Ordering::Release); + Ok(()) +} +``` + +**`SchemaMigrator` implementation**: + +`create_database_tables()` skips the legacy bootstrap (PostgreSQL has no pre-v4 databases) +and calls `MIGRATOR.run()` directly: + +```rust +async fn create_database_tables(&self) -> Result<(), Error> { + // PostgreSQL is a new backend — no legacy databases exist without _sqlx_migrations. + // MIGRATOR.run() always takes the fresh-database path. + MIGRATOR + .run(&self.pool) + .await + .map_err(|e| Error::migration_error(e, DRIVER))?; + Ok(()) +} +``` + +`drop_database_tables()` drops all five tables including `_sqlx_migrations` so the +drop/create cycle used in the test suite works correctly. Use `DROP TABLE IF EXISTS` +consistently for all drops, matching the style established in `1525-06`: + +```rust +async fn drop_database_tables(&self) -> Result<(), Error> { + sqlx::query("DROP TABLE IF EXISTS _sqlx_migrations") + .execute(&self.pool).await?; + sqlx::query("DROP TABLE IF EXISTS torrent_aggregate_metrics") + .execute(&self.pool).await?; + sqlx::query("DROP TABLE IF EXISTS whitelist") + .execute(&self.pool).await?; + sqlx::query("DROP TABLE IF EXISTS torrents") + .execute(&self.pool).await?; + sqlx::query("DROP TABLE IF EXISTS keys") + .execute(&self.pool).await?; + Ok(()) +} +``` + +**SQL syntax differences from SQLite and MySQL**: + +| Aspect | SQLite / MySQL | PostgreSQL | +| --------------------- | ----------------------------------------------------------------- | ---------------------------------------------------- | +| Parameter placeholder | `?` | `$1`, `$2`, … | +| Upsert | `ON DUPLICATE KEY UPDATE` (MySQL) or `INSERT OR REPLACE` (SQLite) | `ON CONFLICT (col) DO UPDATE SET col = EXCLUDED.col` | +| Auto-increment (DDL) | `AUTO_INCREMENT` / `AUTOINCREMENT` | `SERIAL` (in migration files only) | + +**Counter encode/decode helpers** (identical contract to SQLite and MySQL): + +```rust +fn decode_counter(value: i64) -> Result<NumberOfDownloads, Error> { + u64::try_from(value).map_err(|err| Error::invalid_query(DRIVER, err)) +} + +fn encode_counter(value: NumberOfDownloads) -> Result<i64, Error> { + i64::try_from(value).map_err(|err| Error::invalid_query(DRIVER, err)) +} +``` + +Use these helpers in every place a counter column is read from or written to the database. +Do not use bare `as i64` casts or `as u64` casts. + +**`TorrentMetricsStore`, `WhitelistStore`, `AuthKeyStore` implementations**: Follow the same +structure as the SQLite and MySQL drivers, substituting `$1`/`$2` placeholders and the +PostgreSQL upsert syntax. There are no behavior differences relative to the other backends. + +### Driver factory + +In `packages/tracker-core/src/databases/driver/mod.rs`: + +- Add `PostgreSQL` variant to the `Driver` enum. +- Add a `pub mod postgres;` declaration. +- Add a match arm in `build()`: + + ```rust + Driver::PostgreSQL => { + let backend = Postgres::new(db_path)?; + Ok(Arc::new(Box::new(backend) as Box<dyn Database>)) + } + ``` + +### Database setup + +In `packages/tracker-core/src/databases/setup.rs`, extend the configuration-to-internal +driver enum conversion: + +```rust +torrust_tracker_configuration::Driver::PostgreSQL => Driver::PostgreSQL, +``` + +### Default configuration file + +Add `share/default/config/tracker.container.postgresql.toml` modelled on the existing MySQL +container config. The PostgreSQL connection string points to a service named `postgres`: + +```toml +[core.database] +driver = "postgresql" +path = "postgresql://postgres:postgres@postgres:5432/torrust_tracker" +``` + +All other sections remain the same as the existing container configs. + +### Driver tests + +Add an inline `#[cfg(test)]` module in `postgres.rs`. The test is guarded by an environment +variable to avoid requiring a PostgreSQL container in every `cargo test` run. + +**Environment variables**: + +| Variable | Purpose | Default | +| ------------------------------------------------ | ------------------------------------------ | ------------------------- | +| `TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST` | Enable the test (must be set to any value) | unset → test is skipped | +| `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_URL` | Use an already-running PostgreSQL instance | unset → start a container | +| `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE` | PostgreSQL Docker image name | `postgres` | +| `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG` | PostgreSQL Docker image tag | `16` | + +**Test container defaults** (when no URL is provided): + +```text +internal port: 5432 +database: torrust_tracker_test +user: postgres +password: test +``` + +Start the container using `testcontainers::GenericImage` (already a dev-dependency from +MySQL tests). Set container env vars `POSTGRES_PASSWORD`, `POSTGRES_USER`, `POSTGRES_DB`. + +**Test function skeleton**: + +```rust +#[tokio::test] +async fn run_postgres_driver_tests() -> Result<(), Box<dyn std::error::Error + 'static>> { + if std::env::var("TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST").is_err() { + return Ok(()); + } + let db_url = /* resolve from env or start container */; + let driver = Postgres::new(&db_url)?; + super::tests::run_tests(&driver).await; + Ok(()) +} +``` + +**Shared test suite**: reuse the `tests::run_tests()` function already used by the SQLite and +MySQL test modules. All three backends must pass the same set of behavioral scenarios (torrent +CRUD, whitelist CRUD, auth key CRUD, schema drop/create cycle). + +## Tasks + +### Task 1 — Add `Driver::PostgreSQL` to the configuration package + +Steps: + +- Add `PostgreSQL` variant to the `Driver` enum in + `packages/configuration/src/v2_0_0/database.rs`. +- Extend `mask_secrets()` to handle the PostgreSQL URL (share a branch with the MySQL case). +- Add test `it_should_allow_masking_the_postgresql_user_password`. + +Acceptance criteria: + +- [ ] `Driver::PostgreSQL` serializes as `"postgresql"` in TOML. +- [ ] `mask_secrets()` correctly redacts the password in a PostgreSQL URL. +- [ ] The new test passes. + +### Task 2 — Add sqlx `postgres` feature and create PostgreSQL migration files + +Steps: + +- Add `"postgres"` to the `sqlx` features in `packages/tracker-core/Cargo.toml`. +- Create `packages/tracker-core/migrations/postgresql/` with the four migration files listed + in the "What Changes" section above. +- Verify the SQL content is correct by running each migration in sequence against a temporary + PostgreSQL database and confirming the expected schema is produced. + +Acceptance criteria: + +- [ ] `packages/tracker-core/migrations/postgresql/` contains exactly four files with the + same timestamps as the SQLite and MySQL directories. +- [ ] Migration 1 creates `whitelist`, `torrents`, and `keys` with PostgreSQL DDL (`SERIAL`, + no backtick quoting, `$1`/`$2` placeholders in DML). +- [ ] Migration 2 makes `keys.valid_until` nullable. +- [ ] Migration 3 creates `torrent_aggregate_metrics`. +- [ ] Migration 4 widens `torrents.completed` and `torrent_aggregate_metrics.value` to + `BIGINT` using `ALTER COLUMN ... TYPE BIGINT` syntax. +- [ ] Running all four migrations in sequence produces a schema consistent with the SQLite + and MySQL schemas after their four migrations. + +### Task 3 — Implement the PostgreSQL driver + +Create `packages/tracker-core/src/databases/driver/postgres.rs` with: + +- `Postgres` struct (pool, `schema_ready` latch, `schema_lock` mutex). +- `Postgres::new(db_path: &str) -> Result<Self, Error>` using `PgConnectOptions` and + `PgPoolOptions::connect_lazy_with()`. +- `static MIGRATOR: Migrator = sqlx::migrate!("migrations/postgresql");` +- `ensure_schema()` latch — same double-checked pattern as SQLite and MySQL. +- `SchemaMigrator` impl: `create_database_tables()` (MIGRATOR.run() only, no legacy + bootstrap) and `drop_database_tables()` (all five tables with `DROP TABLE IF EXISTS`). +- `TorrentMetricsStore`, `WhitelistStore`, `AuthKeyStore` impls — same semantics as the + other backends, using `$1`/`$2` placeholders and PostgreSQL upsert syntax. +- `decode_counter`/`encode_counter` helpers. + +Acceptance criteria: + +- [ ] `Postgres` satisfies the `Database` aggregate supertrait through the blanket impl + (no manual `impl Database for Postgres {}` block). +- [ ] `create_database_tables()` calls `MIGRATOR.run()` with no legacy bootstrap. +- [ ] `drop_database_tables()` drops all five tables including `_sqlx_migrations`. +- [ ] All counter reads use `decode_counter`; all counter writes use `encode_counter`. +- [ ] No bare `as i64` or `as u64` casts in the driver. + +### Task 4 — Wire the PostgreSQL driver into the factory and setup + +Steps: + +- In `packages/tracker-core/src/databases/driver/mod.rs`: + - Add `PostgreSQL` to the `Driver` enum. + - Add `pub mod postgres;`. + - Add the `Driver::PostgreSQL` arm in `build()`. +- In `packages/tracker-core/src/databases/setup.rs`: + - Add `torrust_tracker_configuration::Driver::PostgreSQL => Driver::PostgreSQL`. + +Acceptance criteria: + +- [ ] `cargo build --workspace` succeeds with `driver = "postgresql"` in a config file. +- [ ] `databases/setup.rs` correctly dispatches to the PostgreSQL driver when the + configuration specifies `driver = "postgresql"`. + +### Task 5 — Add the PostgreSQL driver tests + +Add an inline `#[cfg(test)]` module to `postgres.rs` as described in the "Driver tests" +section above. + +Steps: + +- Implement `run_postgres_driver_tests` guarded by + `TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST`. +- Support both a pre-existing PostgreSQL instance (via + `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_URL`) and a `testcontainers` container started + on demand. +- Default container tag: `16`. Image tag injection via + `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG` (enables the compatibility matrix loop + in Task 6). +- Call `tests::run_tests(&driver).await` — the shared test suite used by all backends. + +Acceptance criteria: + +- [ ] `TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST` is unset → test returns immediately + without error. +- [ ] When the env var is set, the test starts a PostgreSQL container (or connects to the + provided URL), runs the shared test suite, and passes. +- [ ] The container started by the test is removed unconditionally on completion or failure. + +### Task 6 — Extend the compatibility matrix (completing subissue 1525-01) + +Steps: + +- In `contrib/dev-tools/qa/run-db-compatibility-matrix.sh`, add: + - A test for the PostgreSQL configuration URL masking (after the existing protocol tests): + + ```bash + cargo test -p torrust-tracker-configuration postgresql_user_password -- --nocapture + ``` + + - A PostgreSQL versions loop after the MySQL loop: + + ```bash + POSTGRES_VERSIONS_STRING="${POSTGRES_VERSIONS:-14 15 16 17}" + read -r -a POSTGRES_VERSIONS <<< "$POSTGRES_VERSIONS_STRING" + + for version in "${POSTGRES_VERSIONS[@]}"; do + print_heading "PostgreSQL ${version}" + docker pull "postgres:${version}" + TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST=1 \ + TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG="${version}" \ + cargo test -p bittorrent-tracker-core run_postgres_driver_tests -- --nocapture + done + ``` + + - `POSTGRES_VERSIONS` defaults to `14 15 16 17`; override via env var. + +- The script already has `set -euo pipefail`; failures in the PostgreSQL loop will abort + the script with the failing version visible in the output. + +Acceptance criteria: + +- [ ] The script runs the PostgreSQL driver test for each version in `POSTGRES_VERSIONS`. +- [ ] The `POSTGRES_VERSIONS` set is overridable via env var. +- [ ] The script fails fast on the first failing backend/version combination. +- [ ] The script runs successfully end-to-end in a clean environment; a passing run log is + included in the PR description. +- [ ] The compatibility matrix exercises PostgreSQL 14, 15, 16, and 17 by default. + +### Task 7 — Extend the qBittorrent E2E runner with PostgreSQL (completing subissue 1525-02) + +The qBittorrent E2E runner introduced in subissue `1525-02` uses SQLite only. This task +extends it to support PostgreSQL and MySQL. MySQL E2E support (`--db-driver mysql`) is new +work introduced here — it was explicitly out of scope in `1525-02`. It is included here to +avoid a fourth subissue for a minor change and to keep all three backends consistent. + +Steps: + +- Add a `--db-driver` CLI argument to the E2E runner binary. Accept `sqlite3`, `mysql`, and + `postgresql`. Default: `sqlite3` (preserving existing behavior). +- When `--db-driver postgresql` is specified: + - Start a PostgreSQL container via `testcontainers::GenericImage` (or a `DockerCompose` + stack if a compose file is preferred). Wait for the container to be ready before starting + the tracker. Readiness can be checked by attempting a database connection or by running + `pg_isready` inside the container via `docker exec`. + - Generate a tracker config with `driver = "postgresql"` and the appropriate connection URL. + - Run the rest of the E2E scenario unchanged (seeder → tracker → leecher flow is + database-agnostic). +- Reuse the `Drop` guard pattern from the existing runner for unconditional PostgreSQL + container cleanup. +- Add a CI step (or extend the existing E2E step) that exercises `--db-driver postgresql`. +- Document the `--db-driver` argument in the binary's module doc comment. + +Acceptance criteria: + +- [ ] The E2E runner completes a full seeder → leecher download with PostgreSQL as the + backend. +- [ ] No orphaned containers remain on success or failure. +- [ ] The `--db-driver` argument is documented in the binary's module doc comment. + +### Task 8 — Extend the benchmark runner with PostgreSQL (completing subissue 1525-03) + +The benchmark runner introduced in subissue `1525-03` supports SQLite and MySQL. Extend it to +also benchmark PostgreSQL. + +Steps: + +- Add `postgresql` as an accepted value for `--dbs` in the benchmark runner CLI. +- Add `contrib/dev-tools/bench/compose.bench-postgresql.yaml` following the same structure as + the MySQL compose file: tracker service + PostgreSQL service, parameterized tracker image tag + via env var, no fixed host ports, `healthcheck` defined for each service. +- Wire the PostgreSQL compose file into the runner's per-suite lifecycle (same as MySQL/SQLite: + `DockerCompose::up()`, port discovery, workloads, `DockerCompose::down()` via `Drop` guard). +- Re-run the benchmark with both SQLite, MySQL, and PostgreSQL and update + `docs/benchmarks/baseline.md` and `docs/benchmarks/baseline.json` with the new results. + +Acceptance criteria: + +- [ ] `--dbs postgresql` produces benchmark results. +- [ ] `compose.bench-postgresql.yaml` starts and stops cleanly with no orphaned resources. +- [ ] `docs/benchmarks/baseline.md` is updated and includes PostgreSQL results. + +### Task 9 — Add the default PostgreSQL container config, update docs, and fix spell-check + +Steps: + +- Add `share/default/config/tracker.container.postgresql.toml` as described in the + "What Changes" section. +- Update user-facing documentation to document PostgreSQL as a supported backend: + - `README.md` — add `postgresql` to the list of supported database backends. + - `docs/containers.md` — add a section (or extend the existing database section) describing + how to run the tracker with PostgreSQL, including the `POSTGRES_DB` pre-creation + requirement and a reference to the new container config file. +- Run `linter cspell` and add any new technical terms to `project-words.txt` in alphabetical + order. Terms likely to be flagged: `postgresql` (lowercase), `isready`, and any other + identifiers used in scripts or code comments. + +Acceptance criteria: + +- [ ] `share/default/config/tracker.container.postgresql.toml` exists and is valid TOML. +- [ ] The container configuration or its companion documentation (compose file or README) + creates the `torrust_tracker` database (via `POSTGRES_DB` env var or equivalent) before + the tracker is started. +- [ ] The tracker starts successfully when pointed at this config with a running PostgreSQL + container named `postgres`. +- [ ] `README.md` lists PostgreSQL as a supported database backend. +- [ ] `docs/containers.md` documents how to run the tracker with PostgreSQL and states the + database pre-creation requirement. +- [ ] `linter cspell` reports no new failures. + +## Out of Scope + +- Changing consumer wiring from `Arc<Box<dyn Database>>` to narrow trait objects. Deferred + until the MSRV reaches 1.76 (trait-object upcasting). +- PostgreSQL-specific performance tuning or connection pool size configuration beyond the + default `PgPoolOptions` settings. +- Down migrations (rollback support). +- TLS configuration for the PostgreSQL connection (can be expressed in the URL without code + changes). +- Any persistence redesign not required for the driver to work. +- UDP E2E testing against PostgreSQL (can be added later without redesigning the E2E setup). + +## Acceptance Criteria + +- [ ] `Driver::PostgreSQL` serializes as `"postgresql"` in TOML; the configuration package + compiles cleanly. +- [ ] `mask_secrets()` redacts the password from a PostgreSQL URL. +- [ ] `packages/tracker-core/migrations/postgresql/` contains four migration files with the + same timestamps as SQLite and MySQL. +- [ ] Migration 1 creates the tables with PostgreSQL DDL (`SERIAL`, no backtick quoting). +- [ ] Migration 4 widens `torrents.completed` and `torrent_aggregate_metrics.value` to + `BIGINT` using `ALTER COLUMN ... TYPE BIGINT` syntax. +- [ ] `packages/tracker-core/src/databases/driver/postgres.rs` exists and satisfies + `Database` through the blanket impl (no manual `impl Database for Postgres {}`). +- [ ] `create_database_tables()` calls `MIGRATOR.run()` with no legacy bootstrap. +- [ ] `drop_database_tables()` drops all five tables including `_sqlx_migrations`. +- [ ] All counter reads/writes use `decode_counter`/`encode_counter`; no bare truncating + casts. +- [ ] The shared driver test suite passes against PostgreSQL when + `TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST` is set. +- [ ] `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG` controls the PostgreSQL version used + in tests, enabling the compatibility matrix loop. +- [ ] `run-db-compatibility-matrix.sh` loops over `POSTGRES_VERSIONS` (default: + `14 15 16 17`). +- [ ] The qBittorrent E2E runner completes a full download cycle with PostgreSQL. +- [ ] The benchmark runner produces results for PostgreSQL; `docs/benchmarks/baseline.md` + is updated. +- [ ] `share/default/config/tracker.container.postgresql.toml` exists and is valid TOML. +- [ ] `project-words.txt` is up to date; `linter cspell` reports no failures. +- [ ] `README.md` lists PostgreSQL as a supported database backend. +- [ ] `docs/containers.md` documents how to run the tracker with PostgreSQL and states the + database pre-creation requirement. +- [ ] Persistence benchmarking shows no regression for SQLite or MySQL against the committed + baseline. +- [ ] `cargo test --workspace --all-targets` passes. +- [ ] `cargo machete` reports no unused dependencies. +- [ ] `linter all` exits with code `0`. + +## References + +- EPIC: `#1525` — `docs/issues/1525-overhaul-persistence.md` +- Subissue `1525-01`: `docs/issues/1525-01-persistence-test-coverage.md` — compatibility + matrix structure (PostgreSQL loop deferred here) +- Subissue `1525-02`: `docs/issues/1525-02-qbittorrent-e2e.md` — E2E runner (PostgreSQL + deferred here) +- Subissue `1525-03`: `docs/issues/1525-03-persistence-benchmarking.md` — benchmark runner + (PostgreSQL deferred here) +- Subissue `1525-06`: `docs/issues/1525-06-introduce-schema-migrations.md` — migration + framework and history-alignment pattern +- Subissue `1525-07`: `docs/issues/1525-07-align-rust-and-db-types.md` — fourth migration + and `NumberOfDownloads = u64` +- Reference PR: `#1695` +- Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout + instructions +- Reference files: + - `packages/configuration/src/v2_0_0/database.rs` (`Driver::PostgreSQL`, URL masking) + - `packages/tracker-core/src/databases/driver/postgres.rs` (full driver) + - `packages/tracker-core/src/databases/driver/mod.rs` (`Driver::PostgreSQL` in `build()`) + - `packages/tracker-core/src/databases/setup.rs` (PostgreSQL dispatch) + - `packages/tracker-core/migrations/postgresql/` (all four migration files) + - `share/default/config/tracker.container.postgresql.toml` + - `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` (PostgreSQL versions loop) + - `contrib/dev-tools/qa/run-qbittorrent-e2e.py` (E2E reference with PostgreSQL) + - `contrib/dev-tools/qa/run-before-after-db-benchmark.py` (benchmark with PostgreSQL) diff --git a/docs/issues/1525-overhaul-persistence.md b/docs/issues/1525-overhaul-persistence.md new file mode 100644 index 000000000..f1b3e623b --- /dev/null +++ b/docs/issues/1525-overhaul-persistence.md @@ -0,0 +1,150 @@ +# Issue #1525 Implementation Plan (Overhaul Persistence) + +## Goal + +Redesign the persistence layer progressively so PostgreSQL support can be added safely, with each step independently reviewable and mergeable. + +## Scope + +- Target issue: https://github.com/torrust/torrust-tracker/issues/1525 +- Reference PR: https://github.com/torrust/torrust-tracker/pull/1695 +- Review record PR: https://github.com/torrust/torrust-tracker/pull/1700 +- Key review comment: https://github.com/torrust/torrust-tracker/pull/1695#pullrequestreview-4127741472 +- Reference branch for existing implementation work: `review/pr-1695` + +## Context + +This EPIC was created in May 2025, almost a year before the current implementation effort. The problems it describes were identified early, and the opening of PR #1695 (PostgreSQL support) is what turned the plan into an active priority — but PostgreSQL is not the only driver. + +### Original motivations (from issue #1525) + +- **No migrations**: The tracker has no schema migration mechanism. As more tables are planned (e.g. extended metrics from issue #1437), the absence of migrations becomes increasingly risky. +- **Wrong crate for the job**: `r2d2` is a synchronous connection-pool library. It is not clear it is still the best fit; `sqlx` is already used in the Index project and supports async natively. The issue references SeaORM as an alternative worth researching. +- **Adding a new driver is too hard**: The `Database` trait is too wide. Adding PostgreSQL support (issue #462) was confirmed to be tricky with the current `r2d2`-based abstraction — the trait must be split before new backends can be added cleanly. + +### Immediate trigger + +PR #1695 demonstrates that the PostgreSQL work is feasible, but bundled the entire redesign into one large diff. This plan re-delivers that work incrementally so every step is independently reviewable and mergeable. + +### Why now + +The PostgreSQL PR created momentum and a concrete reference implementation. Leaving the redesign for later would mean adding more complexity on top of a layer that is already known to be the wrong shape. + +## Delivery Strategy + +Apply the redesign in small steps that can be merged independently into `develop`. + +### Phase 1: Make the change easy + +1. Add a DB compatibility matrix across supported database versions. +2. Add an end-to-end test with a real BitTorrent client. +3. Add before/after persistence benchmarking so later changes can be compared against a concrete baseline. +4. Split the persistence traits to reduce coupling. +5. Migrate existing SQL backends to the new async `sqlx` substrate without introducing PostgreSQL yet. +6. Introduce schema migrations and align schema ownership with migrations. +7. Align Rust types with the actual SQL storage model. This step may require schema changes (e.g. widening 32-bit counter columns to 64-bit), so it belongs after migrations are in place. + +### Phase 2: Make the easy change + +1. Add PostgreSQL as a first-class backend on top of the refactored persistence layer. + +## Working Rules + +- Treat `review/pr-1695` as a read-only reference branch. +- Do not try to preserve the original PR commit structure. +- Port useful code selectively from the reference branch into clean subissue branches. +- New QA and tooling code should be written in Rust unless there is a strong reason not to. +- Every subissue should produce a PR that is reviewable on its own and safe to merge before PostgreSQL support is complete. + +## Reference Implementation + +PR #1695 was authored on the fork `josecelano/torrust-tracker`, branch `pr-1684-review`. +The reference implementation lives at: + +```text +https://github.com/josecelano/torrust-tracker/tree/pr-1684-review +``` + +This branch should be treated as a **read-only reference** — a prototype that demonstrates +feasibility. Implementation work is done in dedicated subissue branches cut from `develop`. + +### Checking out the reference branch locally + +To inspect the reference implementation without affecting your current checkout, clone the +fork into a separate directory: + +```bash +git clone --branch pr-1684-review \ + https://github.com/josecelano/torrust-tracker.git \ + /path/to/torrust-tracker-pr-1700 +``` + +Replace `/path/to/torrust-tracker-pr-1700` with any directory outside your main checkout. +You can then browse or search it while working in the main repository. + +## Proposed Subissues + +### 1) Add DB compatibility matrix + +- Spec file: `docs/issues/1525-01-persistence-test-coverage.md` +- Outcome: compatibility matrix exercises SQLite and multiple MySQL versions; PostgreSQL slot + reserved for subissue 8 + +### 2) Add qBittorrent end-to-end test + +- Spec file: `docs/issues/1525-02-qbittorrent-e2e.md` +- Outcome: one complete seeder/leecher torrent-sharing scenario using real containerized clients + and docker compose, with SQLite as the backend + +### 3) Add persistence benchmarking + +- Spec file: `docs/issues/1525-03-persistence-benchmarking.md` +- Outcome: reproducible before/after performance measurements across supported backends + +### 4) Split the persistence traits by context + +- Spec file: `docs/issues/1525-04-split-persistence-traits.md` +- Outcome: smaller interfaces with lower coupling and clearer responsibilities + +### 5) Migrate SQLite and MySQL drivers to async `sqlx` + +- Spec file: `docs/issues/1525-05-migrate-sqlite-and-mysql-to-sqlx.md` +- Outcome: shared async persistence substrate without adding PostgreSQL yet + +### 6) Introduce schema migrations + +- Spec file: `docs/issues/1525-06-introduce-schema-migrations.md` +- Outcome: schema changes become explicit, versioned, and testable + +### 7) Align persisted counters and Rust/SQL type boundaries + +- Spec file: `docs/issues/1525-07-align-rust-and-db-types.md` +- Outcome: explicit contract for persisted counters and numeric ranges, with any needed schema + changes delivered through migrations + +### 8) Add PostgreSQL driver support + +- Spec file: `docs/issues/1525-08-add-postgresql-driver.md` +- Outcome: PostgreSQL support lands on top of the refactored and migration-backed persistence + layer; PostgreSQL is added to the compatibility matrix (subissue 1) and qBittorrent E2E + (subissue 2) test harnesses + +## PR Strategy + +- Current branch for the planning docs: `1525-persistence-plan` +- Merge this planning PR into `develop` first. +- After the planning PR is merged, create one branch per subissue from `develop`. +- Keep the PRs narrow and link them back to this EPIC. + +## Acceptance Criteria + +- [ ] The EPIC plan is merged into `develop`. +- [ ] Each subissue has its own specification file in `docs/issues/`. +- [ ] The implementation order is explicit and justified. +- [ ] The plan references PR #1695 and PR #1700 as historical context, not as the delivery vehicle. + +## References + +- Related issue: #1525 +- Related PRs: #1695, #1700 +- Related discussion: PostgreSQL support request #462 diff --git a/project-words.txt b/project-words.txt index 9458ebbf3..0d9668782 100644 --- a/project-words.txt +++ b/project-words.txt @@ -53,6 +53,7 @@ Cyberneering dashmap datagram datetime +dbname debuginfo Deque Dijke @@ -88,6 +89,7 @@ infohashes infoschema Intermodal intervali +isready Joakim kallsyms Karatay @@ -195,6 +197,7 @@ uroot usize Vagaa valgrind +VARCHAR Vitaly vmlinux Vuze @@ -268,4 +271,14 @@ Agentic agentskills frontmatter MSRV +newtypes +sqlx +subissue +Subissue +Subissues rustup +pipefail +qbittorrent +stabilised +supertrait +upcasting From ee599dccd9db5eefcbf5e2fb83b7cece81f2bb56 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Tue, 21 Apr 2026 22:09:36 +0100 Subject: [PATCH 72/79] docs(issues): address Copilot review comments on PR #1702 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - project-words.txt: sort newly-appended words alphabetically - 1525-06: fix double semicolon typo in MIGRATOR.run() snippet - 1525-07: replace "reversible" with "tracked as a forward schema change" — sqlx has no down/rollback migrations - 1525-08: fix migration-1 valid_until type (BIGINT → INTEGER to align with other backends; migration-4 widens to BIGINT) - 1525-08: fix Error::migration_error argument order (e, DRIVER) → (DRIVER, e) to match the signature used throughout 1525-06 --- docs/issues/1525-06-introduce-schema-migrations.md | 2 +- docs/issues/1525-07-align-rust-and-db-types.md | 2 +- docs/issues/1525-08-add-postgresql-driver.md | 4 ++-- project-words.txt | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/issues/1525-06-introduce-schema-migrations.md b/docs/issues/1525-06-introduce-schema-migrations.md index c2129b426..b04ab7942 100644 --- a/docs/issues/1525-06-introduce-schema-migrations.md +++ b/docs/issues/1525-06-introduce-schema-migrations.md @@ -277,7 +277,7 @@ async fn bootstrap_legacy_schema(pool: &Pool) -> Result<(), Error> { ```rust async fn create_database_tables(&self) -> Result<(), Error> { bootstrap_legacy_schema(&self.pool).await?; - MIGRATOR.run(&self.pool).await.map_err(|e| Error::migration_error(DRIVER, e))?;; + MIGRATOR.run(&self.pool).await.map_err(|e| Error::migration_error(DRIVER, e))?; Ok(()) } ``` diff --git a/docs/issues/1525-07-align-rust-and-db-types.md b/docs/issues/1525-07-align-rust-and-db-types.md index fe389354c..9b869af34 100644 --- a/docs/issues/1525-07-align-rust-and-db-types.md +++ b/docs/issues/1525-07-align-rust-and-db-types.md @@ -4,7 +4,7 @@ Widen the download-counter type in Rust from `u32` to `u64` and widen the corresponding database columns from `INTEGER` (32-bit, MySQL) to `BIGINT` (64-bit), delivered as a versioned -`sqlx` migration so the change is explicit, testable, and reversible. +`sqlx` migration so the change is explicit, testable, and tracked as a forward schema change. ## Background diff --git a/docs/issues/1525-08-add-postgresql-driver.md b/docs/issues/1525-08-add-postgresql-driver.md index 7582f92ba..2aec9df12 100644 --- a/docs/issues/1525-08-add-postgresql-driver.md +++ b/docs/issues/1525-08-add-postgresql-driver.md @@ -138,7 +138,7 @@ CREATE TABLE IF NOT EXISTS torrents ( CREATE TABLE IF NOT EXISTS keys ( id SERIAL PRIMARY KEY, key VARCHAR(32) NOT NULL UNIQUE, - valid_until BIGINT NOT NULL + valid_until INTEGER NOT NULL ); ``` @@ -286,7 +286,7 @@ async fn create_database_tables(&self) -> Result<(), Error> { MIGRATOR .run(&self.pool) .await - .map_err(|e| Error::migration_error(e, DRIVER))?; + .map_err(|e| Error::migration_error(DRIVER, e))?; Ok(()) } ``` diff --git a/project-words.txt b/project-words.txt index 0d9668782..0f5990a32 100644 --- a/project-words.txt +++ b/project-words.txt @@ -272,13 +272,13 @@ agentskills frontmatter MSRV newtypes +pipefail +qbittorrent +rustup sqlx +stabilised subissue Subissue Subissues -rustup -pipefail -qbittorrent -stabilised supertrait upcasting From 0cc8528666f814c904d848f17be3f8cc7fd74506 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 07:56:26 +0100 Subject: [PATCH 73/79] docs(issues): add missing container changes to 1525-08 spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task 9 was missing two required steps: 1. share/container/entry_script_sh — the container bootstrap script hard-codes only sqlite3 and mysql; without a postgresql elif branch the container exits 1 when that driver is selected. Spec now includes the exact elif block and the updated error message. 2. compose.yaml — the demo compose file only had a mysql service; spec now adds a postgres service (postgres:16, with healthcheck, POSTGRES_DB env var, and a named volume) and updates the tracker's depends_on to include both mysql and postgres. Also extends the overall Acceptance Criteria section with checkboxes for entry_script_sh and compose.yaml. --- docs/issues/1525-08-add-postgresql-driver.md | 67 ++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/issues/1525-08-add-postgresql-driver.md b/docs/issues/1525-08-add-postgresql-driver.md index 2aec9df12..4b2123564 100644 --- a/docs/issues/1525-08-add-postgresql-driver.md +++ b/docs/issues/1525-08-add-postgresql-driver.md @@ -625,11 +625,64 @@ Steps: - Add `share/default/config/tracker.container.postgresql.toml` as described in the "What Changes" section. + +- Update `share/container/entry_script_sh` to handle `postgresql` alongside the existing + `sqlite3` and `mysql` branches. Add an `elif` branch immediately after the `mysql` branch: + + ```sh + elif cmp_lc "$TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER" "postgresql"; then + + # (no database file needed for PostgreSQL) + + # Select default PostgreSQL configuration + default_config="/usr/share/torrust/default/config/tracker.container.postgresql.toml" + ``` + + Also update the error message in the `else` branch to list all three supported backends: + + ```sh + echo "Please Note: Supported Database Types: \"sqlite3\", \"mysql\", \"postgresql\"." + ``` + + The `Containerfile` already copies this file via + `COPY --chmod=0555 ./share/container/entry_script_sh /usr/local/bin/entry.sh`; no + `Containerfile` changes are needed. + +- Update `compose.yaml` to support the PostgreSQL backend alongside the existing MySQL + service: + - Add a `postgres` service using `image: postgres:16`: + + ```yaml + postgres: + image: postgres:16 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 3s + retries: 5 + start_period: 30s + environment: + - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=postgres + - POSTGRES_DB=torrust_tracker + networks: + - server_side + volumes: + - postgres_data:/var/lib/postgresql/data + ``` + + - Add `postgres` to the tracker service's `depends_on` list (alongside `mysql`) so the + tracker waits for whichever backend is healthy. Both DB services start; the tracker + connects to whichever backend the `TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER` + env var selects. This is acceptable for a demo / developer compose file. + + - Add a `postgres_data` named volume to the `volumes:` section. + - Update user-facing documentation to document PostgreSQL as a supported backend: - `README.md` — add `postgresql` to the list of supported database backends. - `docs/containers.md` — add a section (or extend the existing database section) describing how to run the tracker with PostgreSQL, including the `POSTGRES_DB` pre-creation requirement and a reference to the new container config file. + - Run `linter cspell` and add any new technical terms to `project-words.txt` in alphabetical order. Terms likely to be flagged: `postgresql` (lowercase), `isready`, and any other identifiers used in scripts or code comments. @@ -637,6 +690,14 @@ Steps: Acceptance criteria: - [ ] `share/default/config/tracker.container.postgresql.toml` exists and is valid TOML. +- [ ] `share/container/entry_script_sh` has a `postgresql` branch that selects + `tracker.container.postgresql.toml`; the `else` error message lists all three supported + backends. +- [ ] `compose.yaml` has a `postgres` service; the tracker service's `depends_on` includes + both `mysql` and `postgres`; a `postgres_data` volume is declared. +- [ ] `docker compose up` with + `TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER=postgresql` starts the tracker + successfully against the PostgreSQL container. - [ ] The container configuration or its companion documentation (compose file or README) creates the `torrust_tracker` database (via `POSTGRES_DB` env var or equivalent) before the tracker is started. @@ -685,6 +746,12 @@ Acceptance criteria: - [ ] The benchmark runner produces results for PostgreSQL; `docs/benchmarks/baseline.md` is updated. - [ ] `share/default/config/tracker.container.postgresql.toml` exists and is valid TOML. +- [ ] `share/container/entry_script_sh` has a `postgresql` branch; the `else` error message + lists all three supported backends. +- [ ] `compose.yaml` has a `postgres` service; the tracker service's `depends_on` includes + both `mysql` and `postgres`; `docker compose up` with + `TORRUST_TRACKER_CONFIG_OVERRIDE_CORE__DATABASE__DRIVER=postgresql` starts the tracker + successfully. - [ ] `project-words.txt` is up to date; `linter cspell` reports no failures. - [ ] `README.md` lists PostgreSQL as a supported database backend. - [ ] `docs/containers.md` documents how to run the tracker with PostgreSQL and states the From 8efa87f0474f70b4651d693bb9c5cea1c2828535 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 10:39:42 +0100 Subject: [PATCH 74/79] refactor(dev-tools): consolidate git hook scripts under contrib/dev-tools/git MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move scripts/ content to canonical locations: - scripts/install-git-hooks.sh → contrib/dev-tools/git/install-git-hooks.sh - scripts/pre-commit.sh → deleted (duplicate) - contrib/dev-tools/git/hooks/pre-commit.sh → rewritten in new structured style - contrib/dev-tools/git/hooks/pre-push.sh → rewritten in new structured style The new pre-commit.sh uses a STEPS array with per-step timing and PASSED/FAILED output. It excludes nightly toolchain checks and e2e tests (too slow for pre-commit; covered by CI and pre-push). The new pre-push.sh follows the same structured style and retains all checks from the old script including nightly fmt/check/doc and e2e tests. Update all references across agents, skills, workflows, and documentation. --- .githooks/pre-commit | 2 +- .github/agents/committer.agent.md | 4 +- .github/agents/implementer.agent.md | 4 +- .../dev/git-workflow/commit-changes/SKILL.md | 10 +- .../run-pre-commit-checks/SKILL.md | 8 +- .../setup-dev-environment/SKILL.md | 4 +- .../maintenance/update-dependencies/SKILL.md | 4 +- .github/workflows/copilot-setup-steps.yml | 10 +- AGENTS.md | 4 +- contrib/dev-tools/git/hooks/pre-commit.sh | 93 +++++++++++++++-- contrib/dev-tools/git/hooks/pre-push.sh | 99 ++++++++++++++++--- .../dev-tools/git}/install-git-hooks.sh | 2 +- docs/issues/1697-ai-agent-configuration.md | 4 +- scripts/pre-commit.sh | 83 ---------------- 14 files changed, 199 insertions(+), 132 deletions(-) rename {scripts => contrib/dev-tools/git}/install-git-hooks.sh (94%) delete mode 100755 scripts/pre-commit.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 6e4065777..3461943ea 100644 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -4,4 +4,4 @@ set -euo pipefail repo_root="$(git rev-parse --show-toplevel)" -"$repo_root/scripts/pre-commit.sh" \ No newline at end of file +"$repo_root/contrib/dev-tools/git/hooks/pre-commit.sh" \ No newline at end of file diff --git a/.github/agents/committer.agent.md b/.github/agents/committer.agent.md index 016ee2c0f..a8ef84b04 100644 --- a/.github/agents/committer.agent.md +++ b/.github/agents/committer.agent.md @@ -17,7 +17,7 @@ Treat every commit request as a review-and-verify workflow, not as a blind reque - Follow `AGENTS.md` for repository-wide behaviour and `.github/skills/dev/git-workflow/commit-changes/SKILL.md` for commit-specific reference details. -- The pre-commit validation command is `./scripts/pre-commit.sh`. +- The pre-commit validation command is `./contrib/dev-tools/git/hooks/pre-commit.sh`. - Create GPG-signed Conventional Commits (`git commit -S`). ## Required Workflow @@ -25,7 +25,7 @@ Treat every commit request as a review-and-verify workflow, not as a blind reque 1. Read the current branch, `git status`, and the staged or unstaged diff relevant to the request. 2. Summarize the intended commit scope before taking action. 3. Ensure the commit scope is coherent and does not accidentally mix unrelated changes. -4. Run `./scripts/pre-commit.sh` when feasible and fix issues that are directly related to the +4. Run `./contrib/dev-tools/git/hooks/pre-commit.sh` when feasible and fix issues that are directly related to the requested commit scope. 5. Propose a precise Conventional Commit message. 6. Create the commit with `git commit -S` only after the scope is clear and blockers are resolved. diff --git a/.github/agents/implementer.agent.md b/.github/agents/implementer.agent.md index a083a507c..a34033693 100644 --- a/.github/agents/implementer.agent.md +++ b/.github/agents/implementer.agent.md @@ -27,7 +27,7 @@ Reference: [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.ht ## Repository Rules - Follow `AGENTS.md` for repository-wide conventions. -- The pre-commit validation command is `./scripts/pre-commit.sh`. +- The pre-commit validation command is `./contrib/dev-tools/git/hooks/pre-commit.sh`. - Relevant skills to load when needed: - `.github/skills/dev/testing/write-unit-test/SKILL.md` — test naming and Arrange/Act/Assert pattern. - `.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md` — error handling. @@ -82,5 +82,5 @@ description of what was implemented. Do not commit directly — always delegate - Do not implement more than was asked — scope creep is a defect. - Do not suppress compiler warnings or clippy lints without a documented reason. - Do not add dependencies without running `cargo machete` afterward. -- Do not commit code that fails `./scripts/pre-commit.sh`. +- Do not commit code that fails `./contrib/dev-tools/git/hooks/pre-commit.sh`. - Do not skip the audit step, even for small changes. diff --git a/.github/skills/dev/git-workflow/commit-changes/SKILL.md b/.github/skills/dev/git-workflow/commit-changes/SKILL.md index 415ee2895..5d3995d54 100644 --- a/.github/skills/dev/git-workflow/commit-changes/SKILL.md +++ b/.github/skills/dev/git-workflow/commit-changes/SKILL.md @@ -14,13 +14,13 @@ This skill guides you through the complete commit process for the Torrust Tracke ```bash # One-time setup: install the pre-commit Git hook -./scripts/install-git-hooks.sh +./contrib/dev-tools/git/install-git-hooks.sh # Stage changes git add <files> # Commit with conventional format and GPG signature (MANDATORY) -# The pre-commit hook runs ./scripts/pre-commit.sh automatically +# The pre-commit hook runs ./contrib/dev-tools/git/hooks/pre-commit.sh automatically git commit -S -m "<type>[(<scope>)]: <description>" ``` @@ -66,11 +66,11 @@ git commit -S -m "your commit message" ### Git Hook -The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh` +The repository ships a `pre-commit` Git hook that runs `./contrib/dev-tools/git/hooks/pre-commit.sh` automatically on every `git commit`. Install it once after cloning: ```bash -./scripts/install-git-hooks.sh +./contrib/dev-tools/git/install-git-hooks.sh ``` Once installed, the hook fires on every commit and you do not need to run the script manually. @@ -84,7 +84,7 @@ If the hook is not installed, run the script explicitly before committing. > command timeout of **at least 5 minutes** before invoking this script. ```bash -./scripts/pre-commit.sh +./contrib/dev-tools/git/hooks/pre-commit.sh ``` The script runs: diff --git a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md index b0eb24e4d..371c27dfc 100644 --- a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md +++ b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md @@ -10,11 +10,11 @@ metadata: ## Git Hook (Recommended Setup) -The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh` +The repository ships a `pre-commit` Git hook that runs `./contrib/dev-tools/git/hooks/pre-commit.sh` automatically on every `git commit`. Install it once after cloning: ```bash -./scripts/install-git-hooks.sh +./contrib/dev-tools/git/install-git-hooks.sh ``` After installation the hook fires automatically; you do not need to invoke the script @@ -23,14 +23,14 @@ manually before each commit. ## Automated Checks > **⏱️ Expected runtime: ~3 minutes** on a modern developer machine. AI agents must set a -> command timeout of **at least 5 minutes** before invoking `./scripts/pre-commit.sh`. Agents +> command timeout of **at least 5 minutes** before invoking `./contrib/dev-tools/git/hooks/pre-commit.sh`. Agents > with a default per-command timeout below 5 minutes will likely time out and report a false > failure. Run the pre-commit script. **It must exit with code `0` before every commit.** ```bash -./scripts/pre-commit.sh +./contrib/dev-tools/git/hooks/pre-commit.sh ``` The script runs these steps in order: diff --git a/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md b/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md index 1228611b5..dae36c068 100644 --- a/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md +++ b/.github/skills/dev/maintenance/setup-dev-environment/SKILL.md @@ -72,10 +72,10 @@ cargo install cargo-machete # Unused dependency checker Install the project pre-commit hook (one-time, re-run after hook changes): ```bash -./scripts/install-git-hooks.sh +./contrib/dev-tools/git/install-git-hooks.sh ``` -The hook runs `./scripts/pre-commit.sh` automatically on every `git commit`. +The hook runs `./contrib/dev-tools/git/hooks/pre-commit.sh` automatically on every `git commit`. ## Step 8: Smoke Test diff --git a/.github/skills/dev/maintenance/update-dependencies/SKILL.md b/.github/skills/dev/maintenance/update-dependencies/SKILL.md index c0aa1c867..121c99fbb 100644 --- a/.github/skills/dev/maintenance/update-dependencies/SKILL.md +++ b/.github/skills/dev/maintenance/update-dependencies/SKILL.md @@ -37,7 +37,7 @@ cargo update 2>&1 | tee /tmp/cargo-update.txt # If Cargo.lock has no changes, nothing to do — stop here. # Verify -./scripts/pre-commit.sh +./contrib/dev-tools/git/hooks/pre-commit.sh # Commit and push git add Cargo.lock @@ -92,7 +92,7 @@ cargo update --precise {old-version} {crate-name} ```bash cargo machete -./scripts/pre-commit.sh +./contrib/dev-tools/git/hooks/pre-commit.sh ``` Fix any failures before proceeding. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 2017038b9..4b9e90407 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -7,13 +7,13 @@ on: push: paths: - .github/workflows/copilot-setup-steps.yml - - scripts/install-git-hooks.sh - - scripts/pre-commit.sh + - contrib/dev-tools/git/install-git-hooks.sh + - contrib/dev-tools/git/hooks/pre-commit.sh pull_request: paths: - .github/workflows/copilot-setup-steps.yml - - scripts/install-git-hooks.sh - - scripts/pre-commit.sh + - contrib/dev-tools/git/install-git-hooks.sh + - contrib/dev-tools/git/hooks/pre-commit.sh jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up @@ -47,7 +47,7 @@ jobs: run: cargo install cargo-machete - name: Install Git pre-commit hooks - run: ./scripts/install-git-hooks.sh + run: ./contrib/dev-tools/git/install-git-hooks.sh - name: Smoke-check — run all linters run: linter all diff --git a/AGENTS.md b/AGENTS.md index 801bf8eef..15f9d2f51 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,7 +38,7 @@ native IPv4/IPv6 support, private/whitelisted mode, and a management REST API. - `packages/` — Cargo workspace packages (all domain logic lives here; see package catalog below) - `console/` — Console tools (e.g., `tracker-client`) - `contrib/` — Community-contributed utilities (`bencode`) and developer tooling -- `contrib/dev-tools/` — Developer tools: git hooks (`pre-commit.sh`, `pre-push.sh`), +- `contrib/dev-tools/` — Developer tools: git hooks (`pre-commit.sh`, `pre-push.sh`, `install-git-hooks.sh`), container scripts, and init scripts - `tests/` — Integration tests (`integration.rs`, `servers/`) - `docs/` — Project documentation, ADRs, issue specs, and benchmarking guides @@ -127,7 +127,7 @@ All packages live under `packages/`. The workspace version is `3.0.0-develop`. ```sh rustup show # Check active toolchain rustup update # Update toolchain -rustup toolchain install nightly # Optional: only needed for manual cargo +nightly doc; the repo hook runs ./scripts/pre-commit.sh +rustup toolchain install nightly # Optional: only needed for manual cargo +nightly doc; the repo hook runs ./contrib/dev-tools/git/hooks/pre-commit.sh ``` ### Build diff --git a/contrib/dev-tools/git/hooks/pre-commit.sh b/contrib/dev-tools/git/hooks/pre-commit.sh index c1b183fde..b26bcdb1c 100755 --- a/contrib/dev-tools/git/hooks/pre-commit.sh +++ b/contrib/dev-tools/git/hooks/pre-commit.sh @@ -1,10 +1,83 @@ -#!/bin/bash - -cargo +nightly fmt --check && - cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features && - cargo +nightly doc --no-deps --bins --examples --workspace --all-features && - cargo +nightly machete && - cargo +stable build && - CARGO_INCREMENTAL=0 cargo +stable clippy --no-deps --tests --benches --examples --workspace --all-targets --all-features -- -D clippy::correctness -D clippy::suspicious -D clippy::complexity -D clippy::perf -D clippy::style -D clippy::pedantic && - cargo +stable test --doc --workspace && - cargo +stable test --tests --benches --examples --workspace --all-targets --all-features +#!/usr/bin/env bash +# Pre-commit verification script +# Run all mandatory checks before committing changes. +# +# Usage: +# ./contrib/dev-tools/git/hooks/pre-commit.sh +# +# Expected runtime: ~3 minutes on a modern developer machine. +# AI agents: set a per-command timeout of at least 5 minutes before invoking this script. +# +# All steps must pass (exit 0) before committing. + +set -euo pipefail + +# ============================================================================ +# STEPS +# ============================================================================ +# Each step: "description|success_message|command" + +declare -a STEPS=( + "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete" + "Running all linters|All linters passed|linter all" + "Running documentation tests|Documentation tests passed|cargo test --doc --workspace" + "Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features" +) + +# ============================================================================ +# HELPER FUNCTIONS +# ============================================================================ + +format_time() { + local total_seconds=$1 + local minutes=$((total_seconds / 60)) + local seconds=$((total_seconds % 60)) + if [ "$minutes" -gt 0 ]; then + echo "${minutes}m ${seconds}s" + else + echo "${seconds}s" + fi +} + +run_step() { + local step_number=$1 + local total_steps=$2 + local description=$3 + local success_message=$4 + local command=$5 + + echo "[Step ${step_number}/${total_steps}] ${description}..." + + local step_start=$SECONDS + local -a cmd_array + read -ra cmd_array <<< "${command}" + "${cmd_array[@]}" + local step_elapsed=$((SECONDS - step_start)) + + echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))" + echo +} + +trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-commit checks failed!"; echo "Fix the errors above before committing."; echo "=========================================="; exit 1' ERR + +# ============================================================================ +# MAIN +# ============================================================================ + +TOTAL_START=$SECONDS +TOTAL_STEPS=${#STEPS[@]} + +echo "Running pre-commit checks..." +echo + +for i in "${!STEPS[@]}"; do + IFS='|' read -r description success_message command <<< "${STEPS[$i]}" + run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}" +done + +TOTAL_ELAPSED=$((SECONDS - TOTAL_START)) +echo "==========================================" +echo "SUCCESS: All pre-commit checks passed! ($(format_time "${TOTAL_ELAPSED}"))" +echo "==========================================" +echo +echo "You can now safely stage and commit your changes." diff --git a/contrib/dev-tools/git/hooks/pre-push.sh b/contrib/dev-tools/git/hooks/pre-push.sh index 593068cee..55f7dfc50 100755 --- a/contrib/dev-tools/git/hooks/pre-push.sh +++ b/contrib/dev-tools/git/hooks/pre-push.sh @@ -1,11 +1,88 @@ -#!/bin/bash - -cargo +nightly fmt --check && - cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features && - cargo +nightly doc --no-deps --bins --examples --workspace --all-features && - cargo +nightly machete && - cargo +stable build && - CARGO_INCREMENTAL=0 cargo +stable clippy --no-deps --tests --benches --examples --workspace --all-targets --all-features -- -D clippy::correctness -D clippy::suspicious -D clippy::complexity -D clippy::perf -D clippy::style -D clippy::pedantic && - cargo +stable test --doc --workspace && - cargo +stable test --tests --benches --examples --workspace --all-targets --all-features && - cargo +stable run --bin e2e_tests_runner -- --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml" +#!/usr/bin/env bash +# Pre-push verification script +# Run comprehensive checks before pushing changes, including nightly toolchain +# validation and end-to-end tests. +# +# Usage: +# ./contrib/dev-tools/git/hooks/pre-push.sh +# +# Expected runtime: ~15 minutes on a modern developer machine. +# AI agents: set a per-command timeout of at least 30 minutes before invoking this script. +# +# All steps must pass (exit 0) before pushing. + +set -euo pipefail + +# ============================================================================ +# STEPS +# ============================================================================ +# Each step: "description|success_message|command" + +declare -a STEPS=( + "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete" + "Running all linters|All linters passed|linter all" + "Checking format with nightly toolchain|Nightly format check passed|cargo +nightly fmt --check" + "Checking workspace with nightly toolchain|Nightly check passed|cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features" + "Building documentation with nightly toolchain|Nightly documentation built|cargo +nightly doc --no-deps --bins --examples --workspace --all-features" + "Running documentation tests|Documentation tests passed|cargo test --doc --workspace" + "Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features" + "Running E2E tests|E2E tests passed|cargo run --bin e2e_tests_runner -- --config-toml-path ./share/default/config/tracker.e2e.container.sqlite3.toml" +) + +# ============================================================================ +# HELPER FUNCTIONS +# ============================================================================ + +format_time() { + local total_seconds=$1 + local minutes=$((total_seconds / 60)) + local seconds=$((total_seconds % 60)) + if [ "$minutes" -gt 0 ]; then + echo "${minutes}m ${seconds}s" + else + echo "${seconds}s" + fi +} + +run_step() { + local step_number=$1 + local total_steps=$2 + local description=$3 + local success_message=$4 + local command=$5 + + echo "[Step ${step_number}/${total_steps}] ${description}..." + + local step_start=$SECONDS + local -a cmd_array + read -ra cmd_array <<< "${command}" + "${cmd_array[@]}" + local step_elapsed=$((SECONDS - step_start)) + + echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))" + echo +} + +trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-push checks failed!"; echo "Fix the errors above before pushing."; echo "=========================================="; exit 1' ERR + +# ============================================================================ +# MAIN +# ============================================================================ + +TOTAL_START=$SECONDS +TOTAL_STEPS=${#STEPS[@]} + +echo "Running pre-push checks..." +echo + +for i in "${!STEPS[@]}"; do + IFS='|' read -r description success_message command <<< "${STEPS[$i]}" + run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}" +done + +TOTAL_ELAPSED=$((SECONDS - TOTAL_START)) +echo "==========================================" +echo "SUCCESS: All pre-push checks passed! ($(format_time "${TOTAL_ELAPSED}"))" +echo "==========================================" +echo +echo "You can now safely push your changes." diff --git a/scripts/install-git-hooks.sh b/contrib/dev-tools/git/install-git-hooks.sh similarity index 94% rename from scripts/install-git-hooks.sh rename to contrib/dev-tools/git/install-git-hooks.sh index 478377791..16de7fe5a 100755 --- a/scripts/install-git-hooks.sh +++ b/contrib/dev-tools/git/install-git-hooks.sh @@ -2,7 +2,7 @@ # Install project Git hooks from .githooks/ into .git/hooks/. # # Usage: -# ./scripts/install-git-hooks.sh +# ./contrib/dev-tools/git/install-git-hooks.sh # # Run once after cloning the repository. Re-run to update hooks after # they change. diff --git a/docs/issues/1697-ai-agent-configuration.md b/docs/issues/1697-ai-agent-configuration.md index 925f04ea5..3d38eb003 100644 --- a/docs/issues/1697-ai-agent-configuration.md +++ b/docs/issues/1697-ai-agent-configuration.md @@ -197,7 +197,7 @@ tasks can be delegated to focused agents with the right prompt context. **Candidate initial agents**: - `committer` ✅ — commit specialist: reads branch/diff, runs pre-commit checks - (`./scripts/pre-commit.sh`), proposes a GPG-signed Conventional Commit message, and creates + (`./contrib/dev-tools/git/hooks/pre-commit.sh`), proposes a GPG-signed Conventional Commit message, and creates the commit only after scope and checks are clear. Reference: [`torrust-tracker-demo/.github/agents/commiter.agent.md`](https://raw.githubusercontent.com/torrust/torrust-tracker-demo/refs/heads/main/.github/agents/commiter.agent.md) - `implementer` ✅ — software implementer that applies Test-Driven Development and seeks the @@ -277,7 +277,7 @@ Minimum steps to include: - [x] Install `cargo-machete` — `cargo install cargo-machete`; ensures Copilot can run unused dependency checks (`cargo machete`) as required by the essential rules - [x] Smoke-check: run `linter all` to confirm the environment is healthy before Copilot begins -- [x] Install Git pre-commit hooks — `./scripts/install-git-hooks.sh` +- [x] Install Git pre-commit hooks — `./contrib/dev-tools/git/install-git-hooks.sh` Commit message: `ci(copilot): add copilot-setup-steps workflow` diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh deleted file mode 100755 index c360ad6b6..000000000 --- a/scripts/pre-commit.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash -# Pre-commit verification script -# Run all mandatory checks before committing changes. -# -# Usage: -# ./scripts/pre-commit.sh -# -# Expected runtime: ~3 minutes on a modern developer machine. -# AI agents: set a per-command timeout of at least 5 minutes before invoking this script. -# -# All steps must pass (exit 0) before committing. - -set -euo pipefail - -# ============================================================================ -# STEPS -# ============================================================================ -# Each step: "description|success_message|command" - -declare -a STEPS=( - "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete" - "Running all linters|All linters passed|linter all" - "Running documentation tests|Documentation tests passed|cargo test --doc --workspace" - "Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features" -) - -# ============================================================================ -# HELPER FUNCTIONS -# ============================================================================ - -format_time() { - local total_seconds=$1 - local minutes=$((total_seconds / 60)) - local seconds=$((total_seconds % 60)) - if [ "$minutes" -gt 0 ]; then - echo "${minutes}m ${seconds}s" - else - echo "${seconds}s" - fi -} - -run_step() { - local step_number=$1 - local total_steps=$2 - local description=$3 - local success_message=$4 - local command=$5 - - echo "[Step ${step_number}/${total_steps}] ${description}..." - - local step_start=$SECONDS - local -a cmd_array - read -ra cmd_array <<< "${command}" - "${cmd_array[@]}" - local step_elapsed=$((SECONDS - step_start)) - - echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))" - echo -} - -trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-commit checks failed!"; echo "Fix the errors above before committing."; echo "=========================================="; exit 1' ERR - -# ============================================================================ -# MAIN -# ============================================================================ - -TOTAL_START=$SECONDS -TOTAL_STEPS=${#STEPS[@]} - -echo "Running pre-commit checks..." -echo - -for i in "${!STEPS[@]}"; do - IFS='|' read -r description success_message command <<< "${STEPS[$i]}" - run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}" -done - -TOTAL_ELAPSED=$((SECONDS - TOTAL_START)) -echo "==========================================" -echo "SUCCESS: All pre-commit checks passed! ($(format_time "${TOTAL_ELAPSED}"))" -echo "==========================================" -echo -echo "You can now safely stage and commit your changes." From b3d1e6b7ab979ac54a28cc1524fa5a9a5ababfa9 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 11:09:35 +0100 Subject: [PATCH 75/79] fix(dev-tools): address Copilot review suggestions on PR #1704 - AGENTS.md: clarify nightly toolchain is also needed for pre-push checks - pre-push.sh: explicitly use cargo +stable for non-nightly steps to ensure consistent results across machines regardless of default toolchain --- AGENTS.md | 2 +- contrib/dev-tools/git/hooks/pre-push.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 15f9d2f51..4bcbe8459 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -127,7 +127,7 @@ All packages live under `packages/`. The workspace version is `3.0.0-develop`. ```sh rustup show # Check active toolchain rustup update # Update toolchain -rustup toolchain install nightly # Optional: only needed for manual cargo +nightly doc; the repo hook runs ./contrib/dev-tools/git/hooks/pre-commit.sh +rustup toolchain install nightly # Optional: needed for manual cargo +nightly commands and the repo pre-push checks (fmt/check/doc) ``` ### Build diff --git a/contrib/dev-tools/git/hooks/pre-push.sh b/contrib/dev-tools/git/hooks/pre-push.sh index 55f7dfc50..f03c6d5cd 100755 --- a/contrib/dev-tools/git/hooks/pre-push.sh +++ b/contrib/dev-tools/git/hooks/pre-push.sh @@ -19,14 +19,14 @@ set -euo pipefail # Each step: "description|success_message|command" declare -a STEPS=( - "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete" + "Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo +stable machete" "Running all linters|All linters passed|linter all" "Checking format with nightly toolchain|Nightly format check passed|cargo +nightly fmt --check" "Checking workspace with nightly toolchain|Nightly check passed|cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features" "Building documentation with nightly toolchain|Nightly documentation built|cargo +nightly doc --no-deps --bins --examples --workspace --all-features" - "Running documentation tests|Documentation tests passed|cargo test --doc --workspace" - "Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features" - "Running E2E tests|E2E tests passed|cargo run --bin e2e_tests_runner -- --config-toml-path ./share/default/config/tracker.e2e.container.sqlite3.toml" + "Running documentation tests|Documentation tests passed|cargo +stable test --doc --workspace" + "Running all tests|All tests passed|cargo +stable test --tests --benches --examples --workspace --all-targets --all-features" + "Running E2E tests|E2E tests passed|cargo +stable run --bin e2e_tests_runner -- --config-toml-path ./share/default/config/tracker.e2e.container.sqlite3.toml" ) # ============================================================================ From fe8fedac790cd63fc7f2df99b75a995a3e4d9f0e Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 10:07:13 +0100 Subject: [PATCH 76/79] docs(issues): rename and link issue spec 1525-01 to GitHub issue #1703 - Renamed docs/issues/1525-01-persistence-test-coverage.md to docs/issues/1703-1525-01-persistence-test-coverage.md to align the file name with the tracked GitHub issue number - Updated the spec title to include the issue number (#1703) and added a link to https://github.com/torrust/torrust-tracker/issues/1703 - Updated the spec file reference in docs/issues/1525-overhaul-persistence.md to point to the renamed file --- docs/issues/1525-overhaul-persistence.md | 2 +- ...-coverage.md => 1703-1525-01-persistence-test-coverage.md} | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) rename docs/issues/{1525-01-persistence-test-coverage.md => 1703-1525-01-persistence-test-coverage.md} (98%) diff --git a/docs/issues/1525-overhaul-persistence.md b/docs/issues/1525-overhaul-persistence.md index f1b3e623b..e25f09225 100644 --- a/docs/issues/1525-overhaul-persistence.md +++ b/docs/issues/1525-overhaul-persistence.md @@ -86,7 +86,7 @@ You can then browse or search it while working in the main repository. ### 1) Add DB compatibility matrix -- Spec file: `docs/issues/1525-01-persistence-test-coverage.md` +- Spec file: `docs/issues/1703-1525-01-persistence-test-coverage.md` - Outcome: compatibility matrix exercises SQLite and multiple MySQL versions; PostgreSQL slot reserved for subissue 8 diff --git a/docs/issues/1525-01-persistence-test-coverage.md b/docs/issues/1703-1525-01-persistence-test-coverage.md similarity index 98% rename from docs/issues/1525-01-persistence-test-coverage.md rename to docs/issues/1703-1525-01-persistence-test-coverage.md index 9baf1102e..a7f4e23aa 100644 --- a/docs/issues/1525-01-persistence-test-coverage.md +++ b/docs/issues/1703-1525-01-persistence-test-coverage.md @@ -1,4 +1,6 @@ -# Subissue Draft for #1525-01: Add DB Compatibility Matrix +# Subissue #1703 (Draft for #1525-01): Add DB Compatibility Matrix + +- Issue: https://github.com/torrust/torrust-tracker/issues/1703 ## Goal From 7b3d94469a0567ededb22db5f2e45bc6aeb3a702 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 10:35:53 +0100 Subject: [PATCH 77/79] fix(protocol): saturate scrape counters and add regression tests --- .../http-protocol/src/v1/responses/scrape.rs | 20 ++++++++++++++++ .../udp-tracker-server/src/handlers/scrape.rs | 24 +++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/packages/http-protocol/src/v1/responses/scrape.rs b/packages/http-protocol/src/v1/responses/scrape.rs index 022735abc..02c53f4f3 100644 --- a/packages/http-protocol/src/v1/responses/scrape.rs +++ b/packages/http-protocol/src/v1/responses/scrape.rs @@ -131,5 +131,25 @@ mod tests { String::from_utf8(expected_bytes.to_vec()).unwrap() ); } + + #[test] + fn should_saturate_large_download_counts() { + let info_hash = InfoHash::from_bytes(&[0x69; 20]); + let mut scrape_data = ScrapeData::empty(); + scrape_data.add_file( + &info_hash, + SwarmMetadata { + complete: 1, + downloaded: u32::MAX, + incomplete: 3, + }, + ); + + let response = Bencoded::from(scrape_data); + let bytes = response.body(); + let body = String::from_utf8(bytes).unwrap(); + + assert!(body.contains(&format!("downloadedi{}e", i64::from(u32::MAX)))); + } } } diff --git a/packages/udp-tracker-server/src/handlers/scrape.rs b/packages/udp-tracker-server/src/handlers/scrape.rs index 8bac05c1e..92160c2bd 100644 --- a/packages/udp-tracker-server/src/handlers/scrape.rs +++ b/packages/udp-tracker-server/src/handlers/scrape.rs @@ -53,19 +53,22 @@ pub async fn handle_scrape( Ok(build_response(request, &scrape_data)) } +fn udp_counter_from_u32(value: u32) -> i32 { + // Temporary saturation guard for UDP i32 counters. Proper type alignment across Rust and DB layers + // will be addressed in docs/issues/1525-07-align-rust-and-db-types.md. + i32::try_from(value).unwrap_or(i32::MAX) +} + fn build_response(request: &ScrapeRequest, scrape_data: &ScrapeData) -> Response { let mut torrent_stats: Vec<TorrentScrapeStatistics> = Vec::new(); for file in &scrape_data.files { let swarm_metadata = file.1; - #[allow(clippy::cast_possible_truncation)] - let scrape_entry = { - TorrentScrapeStatistics { - seeders: NumberOfPeers(I32::new(i64::from(swarm_metadata.complete) as i32)), - completed: NumberOfDownloads(I32::new(i64::from(swarm_metadata.downloaded) as i32)), - leechers: NumberOfPeers(I32::new(i64::from(swarm_metadata.incomplete) as i32)), - } + let scrape_entry = TorrentScrapeStatistics { + seeders: NumberOfPeers(I32::new(udp_counter_from_u32(swarm_metadata.complete))), + completed: NumberOfDownloads(I32::new(udp_counter_from_u32(swarm_metadata.downloaded))), + leechers: NumberOfPeers(I32::new(udp_counter_from_u32(swarm_metadata.incomplete))), }; torrent_stats.push(scrape_entry); @@ -458,4 +461,11 @@ mod tests { } } } + + #[test] + fn should_saturate_large_download_counts_for_udp_protocol() { + assert_eq!(super::udp_counter_from_u32(u32::MAX), i32::MAX); + assert_eq!(super::udp_counter_from_u32((i32::MAX as u32) + 1), i32::MAX); + assert_eq!(super::udp_counter_from_u32(42), 42); + } } From 6342067c45c4e94b58d0c36a2168cc0480619a7b Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 11:25:26 +0100 Subject: [PATCH 78/79] ci(tracker-core): add mysql compatibility matrix job --- .github/workflows/testing.yaml | 33 ++++++++++-- .../1703-1525-01-persistence-test-coverage.md | 53 ++++++++----------- packages/tracker-core/Cargo.toml | 4 ++ .../src/databases/driver/mysql.rs | 6 ++- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 173613ec3..b4bc0b5d1 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -133,14 +133,41 @@ jobs: name: Run Unit Tests run: cargo test --tests --benches --examples --workspace --all-targets --all-features + database-compatibility: + name: Database Compatibility (${{ matrix.mysql-version }}) + runs-on: ubuntu-latest + needs: unit + + strategy: + matrix: + mysql-version: ["8.0", "8.4"] + + steps: + - id: checkout + name: Checkout Repository + uses: actions/checkout@v6 + + - id: setup + name: Setup Toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - id: cache + name: Enable Job Cache + uses: Swatinem/rust-cache@v2 + - id: database - name: Run MySQL Database Tests - run: TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test --package bittorrent-tracker-core + name: Run Database Compatibility Test + env: + TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST: "true" + TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG: ${{ matrix.mysql-version }} + run: cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_mysql_driver_tests -- --nocapture e2e: name: E2E runs-on: ubuntu-latest - needs: unit + needs: database-compatibility strategy: matrix: diff --git a/docs/issues/1703-1525-01-persistence-test-coverage.md b/docs/issues/1703-1525-01-persistence-test-coverage.md index a7f4e23aa..be5ada114 100644 --- a/docs/issues/1703-1525-01-persistence-test-coverage.md +++ b/docs/issues/1703-1525-01-persistence-test-coverage.md @@ -44,7 +44,7 @@ The implementation must follow these quality rules for all new and modified test The PR #1695 review branch includes a QA script that defines the expected behavior: -- `run-db-compatibility-matrix.sh`: +- `database-compatibility` job in `.github/workflows/testing.yaml`: executes a compatibility matrix across SQLite, multiple MySQL versions, and multiple PostgreSQL versions. @@ -88,38 +88,30 @@ Steps: - PostgreSQL (reserved for subissue #1525-08): `TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG` When `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG` is not set, the test falls back to the - current hardcoded default (e.g. `8.0`), preserving existing behavior. The matrix script sets + current hardcoded default (e.g. `8.0`), preserving existing behavior. The CI matrix job sets this variable explicitly for each version in the loop, so unset means "run as today" and the matrix just expands that into multiple combinations. -- Add `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` modeled after the PR prototype: - - `set -euo pipefail` - - define default version sets from env vars: - - `MYSQL_VERSIONS` defaulting to at least `8.0 8.4` - - `POSTGRES_VERSIONS` reserved for subissue #1525-08 - - run pre-checks once (`cargo check --workspace --all-targets`) - - run protocol/configuration tests once - - run SQLite driver tests once - - loop MySQL versions: `docker pull mysql:<version>`, then run MySQL driver tests with - `TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=1` and - `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG=<version>` - - print a clear heading for each backend/version before executing tests - - fail fast on first failure with the failing backend/version visible in logs - - keep script complexity intentionally low; avoid re-implementing test logic already in test - functions -- Replace the current single MySQL `database` step in `.github/workflows/testing.yaml` with - execution of the new script. +- Add a dedicated `database-compatibility` workflow job (between unit and e2e) with matrix values for MySQL versions: + - include matrix values for at least `8.0` and `8.4` + - run `cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_mysql_driver_tests -- --nocapture` + - set `TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true` + - set `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG=<version>` + - keep the test logic in Rust; use workflow matrix for version fan-out +- Replace the current single MySQL `database` step in `.github/workflows/testing.yaml` with a + dedicated `database-compatibility` job. Acceptance criteria: - [ ] DB image version injection is supported via `TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG` (and a reserved `POSTGRES` equivalent for subissue #1525-08). -- [ ] `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` exists and runs successfully. -- [ ] The script exercises SQLite and at least two MySQL versions by default. +- [ ] `database-compatibility` workflow job runs successfully for each configured MySQL version. +- [ ] The workflow matrix exercises at least two MySQL versions by default. - [ ] Failures identify the backend/version combination that broke. -- [ ] The `database` job step in `.github/workflows/testing.yaml` runs the matrix script instead - of a single-version MySQL command. -- [ ] The script structure allows PostgreSQL to be added in subissue #1525-08 without a redesign. +- [ ] The dedicated `database-compatibility` job in `.github/workflows/testing.yaml` replaces the + old single-version MySQL command. +- [ ] The workflow matrix structure allows PostgreSQL to be added in subissue #1525-08 without a + redesign. - [ ] Tests do not hard-code host ports; `testcontainers` assigns random ports automatically. - [ ] All containers started by tests are removed unconditionally on test completion or failure. @@ -127,12 +119,13 @@ Acceptance criteria: Steps: -- Document the local invocation command for the matrix script. -- Document that the CI `database` step runs the same script. +- Document the local invocation command for the compatibility test using explicit feature + env + vars. +- Document that CI runs the same test through the `database-compatibility` workflow job matrix. Acceptance criteria: -- [ ] The matrix script is documented and runnable without ad hoc manual steps. +- [ ] The compatibility test command is documented and runnable without ad hoc manual steps. ## Out of Scope @@ -145,8 +138,8 @@ Acceptance criteria: - [ ] `cargo test --workspace --all-targets` passes. - [ ] `linter all` exits with code `0`. -- [ ] The matrix script has been executed successfully in a clean environment; a passing run log - is included in the PR description. +- [ ] The `database-compatibility` workflow job has been executed successfully in a clean + environment; a passing run log is included in the PR description. ## References @@ -154,4 +147,4 @@ Acceptance criteria: - Reference PR: #1695 - Reference implementation branch: `josecelano:pr-1684-review` — see EPIC for checkout instructions (`docs/issues/1525-overhaul-persistence.md`) -- Reference script: `contrib/dev-tools/qa/run-db-compatibility-matrix.sh` +- Reference job: `.github/workflows/testing.yaml` `database-compatibility` diff --git a/packages/tracker-core/Cargo.toml b/packages/tracker-core/Cargo.toml index fb864cde7..59c47dda2 100644 --- a/packages/tracker-core/Cargo.toml +++ b/packages/tracker-core/Cargo.toml @@ -13,6 +13,10 @@ repository.workspace = true rust-version.workspace = true version.workspace = true +[features] +default = [ ] +db-compatibility-tests = [ ] + [dependencies] aquatic_udp_protocol = "0" bittorrent-primitives = "0.1.0" diff --git a/packages/tracker-core/src/databases/driver/mysql.rs b/packages/tracker-core/src/databases/driver/mysql.rs index da2f86ce8..3f17e120d 100644 --- a/packages/tracker-core/src/databases/driver/mysql.rs +++ b/packages/tracker-core/src/databases/driver/mysql.rs @@ -345,7 +345,7 @@ impl Database for Mysql { } } -#[cfg(test)] +#[cfg(all(test, feature = "db-compatibility-tests"))] mod tests { use std::sync::Arc; @@ -379,7 +379,9 @@ mod tests { impl StoppedMysqlContainer { async fn run(self, config: &MysqlConfiguration) -> Result<RunningMysqlContainer, Box<dyn std::error::Error + 'static>> { - let container = GenericImage::new("mysql", "8.0") + let image_tag = std::env::var("TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG").unwrap_or_else(|_| "8.0".to_string()); + + let container = GenericImage::new("mysql", image_tag.as_str()) .with_exposed_port(config.internal_port.tcp()) // todo: this does not work //.with_wait_for(WaitFor::message_on_stdout("ready for connections")) From f5237451c2a6f2db595ea8a8e90a2fccb8ad7f22 Mon Sep 17 00:00:00 2001 From: Jose Celano <josecelano@gmail.com> Date: Wed, 22 Apr 2026 12:12:11 +0100 Subject: [PATCH 79/79] test(tracker-core): clarify db compatibility test usage --- packages/http-protocol/src/v1/responses/scrape.rs | 2 +- packages/tracker-core/src/databases/driver/mysql.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/http-protocol/src/v1/responses/scrape.rs b/packages/http-protocol/src/v1/responses/scrape.rs index 02c53f4f3..30319bd6b 100644 --- a/packages/http-protocol/src/v1/responses/scrape.rs +++ b/packages/http-protocol/src/v1/responses/scrape.rs @@ -133,7 +133,7 @@ mod tests { } #[test] - fn should_saturate_large_download_counts() { + fn should_encode_large_download_counts_as_i64() { let info_hash = InfoHash::from_bytes(&[0x69; 20]); let mut scrape_data = ScrapeData::empty(); scrape_data.add_file( diff --git a/packages/tracker-core/src/databases/driver/mysql.rs b/packages/tracker-core/src/databases/driver/mysql.rs index 3f17e120d..ef91eb1f7 100644 --- a/packages/tracker-core/src/databases/driver/mysql.rs +++ b/packages/tracker-core/src/databases/driver/mysql.rs @@ -355,7 +355,8 @@ mod tests { Test for this driver are executed with: - `TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true cargo test` + `TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST=true \ + cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_mysql_driver_tests` The `Database` trait is very simple and we only have one driver that needs a container. In the future we might want to use different approaches like: @@ -456,6 +457,8 @@ mod tests { driver } + // This test is invoked by `.github/workflows/testing.yaml` in the + // `database-compatibility` job to validate supported MySQL versions. #[tokio::test] async fn run_mysql_driver_tests() -> Result<(), Box<dyn std::error::Error + 'static>> { if std::env::var("TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST").is_err() {