diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 44eff67..585d054 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -15,8 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ pkg-config \ clang \ - valkey-server \ - valkey-tools \ + postgresql \ && rm -rf /var/lib/apt/lists/* RUN groupadd --gid ${USER_GID:-1000} $USERNAME \ diff --git a/.env.example b/.env.example index 9f25ae2..1cf4a5e 100644 --- a/.env.example +++ b/.env.example @@ -22,3 +22,5 @@ METRICS_BIND_ADDR= # Sandboxed tool execution # DOCKER_HOST= SANDBOX_MAX_ITERATIONS=8 + +DATABASE_URL= diff --git a/.woodpecker/tests.yml b/.woodpecker/tests.yml index fa79918..e1eda5f 100644 --- a/.woodpecker/tests.yml +++ b/.woodpecker/tests.yml @@ -2,6 +2,14 @@ when: event: - push +services: + - name: postgres + image: postgres:18 + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: steep + steps: - name: fmt image: rust:1.99 @@ -15,10 +23,17 @@ steps: - rustup component add clippy - cargo clippy --workspace --all-targets --all-features -- -D warnings + - name: wait-for-postgres + image: postgres:18 + commands: + - until pg_isready -h postgres -U postgres; do sleep 1; done + - name: test image: rust:1.99 + environment: + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/steep commands: - - cargo test --workspace --all-targets + - cargo test --workspace --all-targets -- --include-ignored - name: container-build image: quay.io/buildah/stable diff --git a/Cargo.lock b/Cargo.lock index fe89039..d04968b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31404e1443b7b7bcaa311c1af456775cc3f668e34573f1503d7ce4844327629e" dependencies = [ - "bitflags", + "bitflags 2.13.1", "bytes", "futures-core", "futures-sink", @@ -29,7 +29,7 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "bitflags", + "bitflags 2.13.1", "bytes", "bytestring", "derive_more", @@ -165,6 +165,51 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.7", + "generic-array", +] + +[[package]] +name = "aegis" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41585f248ed9406567ae6d61ca2a55ed3dc7348e65203a01229881253acb95e3" +dependencies = [ + "cc", + "softaes", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aho-corasick" version = "1.1.5" @@ -174,6 +219,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "allocator-api2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c880a97d28a3681c0267bd29cff89621202715b065127cd445fa0f0fe0aa2880" + [[package]] name = "android_system_properties" version = "0.1.6" @@ -183,60 +240,78 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "antithesis_sdk" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08410fcac93669a476c006cd6c4512ac1e2b30fd117231a5d55d8a2c76599b82" +dependencies = [ + "libc", + "libloading", + "linkme", + "once_cell", + "rand 0.8.8", + "rustc_version_runtime", + "serde", + "serde_json", +] + [[package]] name = "anyhow" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" -[[package]] -name = "apalis" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504d52557a16b7b202941660f339c9182910d498cac40f93d15f6b31e6bef290" -dependencies = [ - "apalis-core", - "futures", - "pin-project-lite", - "serde", - "thiserror", - "tower", - "tracing", - "tracing-futures", -] - -[[package]] -name = "apalis-core" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3948d2051795c769e6a44a46549879af39d5e8e4fb113e0011cf99f7cd21b657" -dependencies = [ - "futures", - "futures-timer", - "pin-project-lite", - "serde", - "serde_json", - "thiserror", - "tower", - "ulid", -] - -[[package]] -name = "apalis-redis" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871367e3dfff2accda824ccc6e4f46f8f155c865065a450c466a7f2835541d55" -dependencies = [ - "apalis-core", - "chrono", - "futures", - "log", - "redis", - "serde", - "thiserror", - "tokio", -] - [[package]] name = "arc-swap" version = "1.9.2" @@ -246,6 +321,49 @@ dependencies = [ "rustversion", ] +[[package]] +name = "aristo" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdeefa800110050103e2459a2f8dbdbd560ad046e30f1f87e24ce19c2cb8bde" +dependencies = [ + "aristo-macros", +] + +[[package]] +name = "aristo-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64a66d21a80182b35b1741997a6d2456911f54b7eb1918aa4e2382fc205268d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "assoc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdc70193dadb9d7287fa4b633f15f90c876915b31f6af17da307fc59c9859a8" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -310,15 +428,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "backon" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" -dependencies = [ - "fastrand", -] - [[package]] name = "backtrace" version = "0.3.76" @@ -334,6 +443,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + [[package]] name = "base64" version = "0.22.1" @@ -352,12 +467,95 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bigdecimal" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa3f3d8cbf4dffcfe4991de61d012bef509a409ecbe9dd41049bfe32b4d4653" +dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.13.1", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex 1.3.0", + "syn 2.0.119", + "which", +] + +[[package]] +name = "bit-set" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d87354e4229f54a44f7bf2435906a4656dba36026ab6eaca629a2c436a691c" +dependencies = [ + "bit-vec", + "serde", +] + +[[package]] +name = "bit-vec" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5727b15fa97d4f4fee0a3b7c3d550ed0269f54329207b86388de918604e31269" +dependencies = [ + "borsh", + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "block2" version = "0.6.2" @@ -410,12 +608,83 @@ dependencies = [ "serde_repr", ] +[[package]] +name = "borrow-or-share" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" + +[[package]] +name = "borsh" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "branches" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7436b21fd6195415058eb41c9090e156b556bc7e0377bb57c5c026a421521525" +dependencies = [ + "rustc_version", +] + [[package]] name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.12.1" @@ -433,12 +702,21 @@ dependencies = [ [[package]] name = "cc" -version = "1.4.4" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630" dependencies = [ "find-msvc-tools", - "shlex", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", ] [[package]] @@ -453,6 +731,23 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +[[package]] +name = "cfg_block" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18758054972164c3264f7c8386f5fc6da6114cb46b619fd365d4e3b2dc3ae487" + +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.45" @@ -460,11 +755,85 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", + "js-sys", "num-traits", - "serde", + "wasm-bindgen", "windows-link", ] +[[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", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "clap_lex" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "combine" version = "4.6.8" @@ -472,13 +841,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", - "futures-core", "memchr", - "pin-project-lite", - "tokio", - "tokio-util", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.16.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width 0.2.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "convert_case" version = "0.10.0" @@ -504,6 +902,48 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.20" @@ -513,12 +953,102 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +[[package]] +name = "crypto-bigint" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a52aa3fcda4e6302a9f48734f234d35d4721b96f8fe07d073f07ce9df4f0271" +dependencies = [ + "cpubits", + "ctutils", + "num-traits", + "rand_core 0.10.1", + "serdect", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "crypto-primes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3633a51a39c69ebbaa4feaa694bd83d241e4093901c84a0963b19d9bb3f0cf8f" +dependencies = [ + "crypto-bigint", + "rand_core 0.10.1", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "ctutils" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" +dependencies = [ + "cmov", +] + +[[package]] +name = "deadpool" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e98a7e119cd347f4201e1159b19831029e203e2d8b790547708e8157b4acf1e" +dependencies = [ + "deadpool-runtime", + "tokio", +] + +[[package]] +name = "deadpool-runtime" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2657f61fb1dd8bf37a8d51093cc7cee4e77125b22f7753f49b289f831bec2bae" +dependencies = [ + "tokio", +] + [[package]] name = "debugid" version = "0.8.0" @@ -530,15 +1060,70 @@ dependencies = [ ] [[package]] -name = "der" -version = "0.8.1" +name = "defmt" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "der_derive", + "flagset", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a" +dependencies = [ + "const-oid 0.10.2", "pem-rfc7468", "zeroize", ] +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "deranged" version = "0.5.8" @@ -586,13 +1171,37 @@ dependencies = [ "tracing", ] +[[package]] +name = "dialoguer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96" +dependencies = [ + "console", + "shell-words", + "tempfile", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", +] + [[package]] name = "dispatch2" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", ] @@ -613,6 +1222,18 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "either" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -622,6 +1243,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -638,6 +1279,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + [[package]] name = "evmap" version = "11.0.0" @@ -649,6 +1300,35 @@ dependencies = [ "smallvec", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fastbloom" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" +dependencies = [ + "getrandom 0.3.4", + "libm", + "siphasher", +] + [[package]] name = "fastrand" version = "2.5.0" @@ -667,9 +1347,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "findshlibs" @@ -683,6 +1363,23 @@ dependencies = [ "winapi", ] +[[package]] +name = "flagset" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" + +[[package]] +name = "fluent-uri" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + [[package]] name = "fnv" version = "1.0.7" @@ -720,19 +1417,10 @@ dependencies = [ ] [[package]] -name = "futures" -version = "0.3.34" +name = "funty" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-channel" @@ -751,14 +1439,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] -name = "futures-executor" -version = "0.3.34" +name = "futures-intrusive" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", - "futures-task", - "futures-util", + "lock_api", + "parking_lot", ] [[package]] @@ -790,19 +1478,12 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" -[[package]] -name = "futures-timer" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" - [[package]] name = "futures-util" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -813,6 +1494,21 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generator" version = "0.8.9" @@ -828,6 +1524,16 @@ dependencies = [ "windows-result", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -836,7 +1542,7 @@ checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -847,16 +1553,44 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + [[package]] name = "h2" version = "0.4.19" @@ -888,6 +1622,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2 0.2.21", + "equivalent", "foldhash", ] @@ -896,6 +1632,41 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2 0.2.21", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "hashlink" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a596f1b20ed2cc5ecac41a164aaebc7258057060f06c0cf7a2ba3991ee7990fb" +dependencies = [ + "hashbrown 0.17.1", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" [[package]] name = "hex" @@ -903,6 +1674,24 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "hostname" version = "0.4.2" @@ -970,6 +1759,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.11.1" @@ -1084,6 +1882,31 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collator" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08984ed58ac439ebf3e13d2cf26b0c46a60afcd21721c1d14087c0b240344dda" +dependencies = [ + "icu_collator_data", + "icu_collections", + "icu_locale_core", + "icu_locale_fallback", + "icu_normalizer", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "zerovec", +] + +[[package]] +name = "icu_collator_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d7e54efdddeb1208c08dd5d32b53a879ac00d2d3d051b2255fd26821d16368" + [[package]] name = "icu_collections" version = "2.3.0" @@ -1098,6 +1921,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "icu_locale" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "785f595c61ef57169a467eeed7b4b6936a66f6cacbb116a96ee86da983251bf4" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_locale_fallback", + "icu_provider", + "tinystr", + "zerovec", +] + [[package]] name = "icu_locale_core" version = "2.3.0" @@ -1106,11 +1944,38 @@ checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", + "serde", "tinystr", "writeable", "zerovec", ] +[[package]] +name = "icu_locale_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37d91460e362a5cf58907cd7ce871411775ee6294e49a5cc8e6cec16dfa75ea" + +[[package]] +name = "icu_locale_fallback" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "251af8e57c9400e3eb58242fe5b8b1152b2a64fdf4cf632f923c38ccee6f2fa9" +dependencies = [ + "icu_locale_core", + "icu_locale_fallback_data", + "icu_provider", + "potential_utf", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locale_fallback_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "decf2a22ec8fa68f1a0c1129a3f8583f8f8bc24e8b9ccbe98ead99f62a4dc3a8" + [[package]] name = "icu_normalizer" version = "2.3.0" @@ -1122,6 +1987,9 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", + "utf16_iter", + "utf8_iter", + "write16", "zerovec", ] @@ -1160,6 +2028,8 @@ checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", + "serde", + "stable_deref_trait", "writeable", "yoke", "zerofrom", @@ -1194,6 +2064,12 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "277ff51754a3f68f12f58446c5d006aa8baa4914ea273cce24a599cfaff33d4f" +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + [[package]] name = "indexmap" version = "2.14.1" @@ -1204,18 +2080,183 @@ dependencies = [ "hashbrown 0.17.1", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +dependencies = [ + "memoffset", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "io-uring" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3bd0ecfbb87805f538bb7b32e5239ca0763890c623e349860ecba69469f2bb" +dependencies = [ + "bitflags 2.13.1", + "cfg-if", + "libc", +] + [[package]] name = "ipnet" version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jiff" +version = "0.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b005715dcbeb0089a3c0dab99f2ff1cc3b2525323552703d648585d342a383" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc9817253cf7c7ee4684451bd327e88d6f3658014e54a29198625590650695c" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8377070c6bae868759445e5a77f66d84f0b72f3a054bfb00e6d038b8282da7" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[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 = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + [[package]] name = "js-sys" version = "0.3.104" @@ -1239,6 +2280,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "left-right" version = "0.11.8" @@ -1256,6 +2303,68 @@ version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +dependencies = [ + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d20bef17f513b9b3004532233187769cd072d790971f4e4da0e346eb6401e8" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linkme" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3045e122bd98aef8ec3ad58ce84f0791f64e70163d1a02710af4aa11a4d54cc5" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77060ebe535362c3da75682cd17b0431017b6e7c5661e714fc69a7ad017d1301" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -1302,6 +2411,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef9ac18847474e638e3702b76c65d4eb93428471a74778ef0f1be711717f89b5" +dependencies = [ + "hashbrown 0.17.1", +] + [[package]] name = "matchers" version = "0.2.0" @@ -1317,12 +2435,31 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "metrics" version = "0.24.6" @@ -1365,18 +2502,46 @@ dependencies = [ "hashbrown 0.16.1", "metrics", "quanta", - "rand", + "rand 0.9.5", "rand_xoshiro", "rapidhash", "sketches-ddsketch", ] +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "miette-derive", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1394,7 +2559,7 @@ checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -1421,12 +2586,22 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "cfg-if", "cfg_aliases", "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1485,7 +2660,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-foundation", ] @@ -1506,7 +2681,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags", + "bitflags 2.13.1", "dispatch2", "objc2", ] @@ -1517,7 +2692,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags", + "bitflags 2.13.1", "dispatch2", "objc2", "objc2-core-foundation", @@ -1550,7 +2725,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -1568,7 +2743,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags", + "bitflags 2.13.1", "block2", "libc", "objc2", @@ -1581,7 +2756,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", ] @@ -1592,19 +2767,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", "objc2-foundation", ] +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "objc2-core-foundation", +] + [[package]] name = "objc2-ui-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags", + "bitflags 2.13.1", "block2", "objc2", "objc2-cloud-kit", @@ -1644,13 +2828,25 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags", + "bitflags 2.13.1", "cfg-if", "foreign-types", "libc", @@ -1703,6 +2899,27 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "pack1" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b7bb0ecf2e447b1f20ee94ee79ef6eed1e9d4b3c36ce1903b9dea3bf205523" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -1726,6 +2943,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "pem-rfc7468" version = "1.0.0" @@ -1741,6 +2964,25 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_shared", + "serde", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.13" @@ -1767,24 +3009,123 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pkcs1" +version = "0.8.0-rc.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f485dbafe293ea6ccaa7d82bc591651a796eb8a9aec3df040b057b706073dbc3" +dependencies = [ + "der 0.8.2", + "spki 0.8.1", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.2", + "spki 0.8.1", +] + [[package]] name = "pkg-config" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +[[package]] +name = "pluralizer" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b3eba432a00a1f6c16f39147847a870e94e2e9b992759b503e330efec778cbe" +dependencies = [ + "once_cell", + "regex", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08808e3c483c46e999108051c78334f473d5adb59d78bb80a1268c7e6aa6c514" +dependencies = [ + "base64 0.22.1", + "byteorder", + "bytes", + "fallible-iterator 0.2.0", + "hmac", + "md-5", + "memchr", + "rand 0.10.3", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851ca9db4932932d69f3ea811b1abe63087a0f740a47692619dd40d4899b68be" +dependencies = [ + "array-init", + "bytes", + "fallible-iterator 0.2.0", + "jiff", + "postgres-protocol", + "uuid", +] + [[package]] name = "potential_utf" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ + "serde_core", + "writeable", "zerovec", ] @@ -1803,6 +3144,25 @@ dependencies = [ "zerocopy", ] +[[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.119", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.107" @@ -1812,6 +3172,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "quanta" version = "0.12.6" @@ -1822,7 +3205,7 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi", ] @@ -1842,14 +3225,58 @@ 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 = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -1859,7 +3286,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", ] [[package]] @@ -1871,13 +3307,28 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rand_xoshiro" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -1895,32 +3346,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags", -] - -[[package]] -name = "redis" -version = "0.32.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "014cc767fefab6a3e798ca45112bccad9c6e0e218fbd49720042716c73cfef44" -dependencies = [ - "arc-swap", - "backon", - "bytes", - "cfg-if", - "combine", - "futures-channel", - "futures-util", - "itoa", - "num-bigint", - "percent-encoding", - "pin-project-lite", - "ryu", - "sha1_smol", - "socket2", - "tokio", - "tokio-util", - "url", + "bitflags 2.13.1", ] [[package]] @@ -1929,7 +3355,27 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.1", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", ] [[package]] @@ -2020,12 +3466,77 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "roaring" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18bd8a37d17a58532776dcdf6041ce64929adca78e8489d5cacbafe99229d3e1" +dependencies = [ + "bytemuck", + "byteorder", +] + +[[package]] +name = "rsa" +version = "0.10.0-rc.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33405e321e16ef941ca66e254f6904c3aafd3c7ff001fb88bf11c73eb75c2b85" +dependencies = [ + "const-oid 0.10.2", + "crypto-bigint", + "crypto-primes", + "digest", + "pkcs1", + "pkcs8", + "rand_core 0.10.1", + "signature", + "spki 0.8.1", + "zeroize", +] + +[[package]] +name = "rsqlite-vfs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" +dependencies = [ + "hashbrown 0.16.1", + "thiserror", +] + +[[package]] +name = "rusqlite" +version = "0.40.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" +dependencies = [ + "bitflags 2.13.1", + "fallible-iterator 0.3.0", + "fallible-streaming-iterator", + "hashlink 0.12.2", + "libsqlite3-sys", + "smallvec", + "sqlite-wasm-rs", +] + [[package]] name = "rustc-demangle" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2035,19 +3546,77 @@ dependencies = [ "semver", ] +[[package]] +name = "rustc_version_runtime" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd18cd2bae1820af0b6ad5e54f4a51d0f3fcc53b05f845675074efcc7af071d" +dependencies = [ + "rustc_version", + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.52.0", +] + [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "rustls-pki-types" version = "1.15.1" @@ -2057,6 +3626,44 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.23" @@ -2069,6 +3676,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.29" @@ -2096,7 +3712,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "core-foundation", "core-foundation-sys", "libc", @@ -2197,7 +3813,7 @@ version = "0.49.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d889520a375e5b93efb0a66def1630d21d168b0251eb55b286b03fa940ccfc84" dependencies = [ - "rand", + "rand 0.9.5", "sentry-types", "serde", "serde_json", @@ -2220,7 +3836,7 @@ version = "0.49.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba6c1bee99be05938885266fe5c95e0e4a2f46722cae205519f26e4ebdddd733" dependencies = [ - "bitflags", + "bitflags 2.13.1", "log", "sentry-core", ] @@ -2256,7 +3872,7 @@ version = "0.49.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77796d14eedbef22c2fe78e9c69fb09f14c7ad607e624d48dce92eedc17a136e" dependencies = [ - "bitflags", + "bitflags 2.13.1", "sentry-backtrace", "sentry-core", "tracing-core", @@ -2271,7 +3887,7 @@ checksum = "fc71f5ca55942d9b2901af95d5df5c5d65c164134c22a83682cac3d0b6c7ef2d" dependencies = [ "debugid", "hex", - "rand", + "rand 0.9.5", "serde", "serde_json", "thiserror", @@ -2345,6 +3961,15 @@ dependencies = [ "syn 3.0.4", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2357,12 +3982,44 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "digest", +] + [[package]] name = "sha1_smol" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2372,12 +4029,44 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "shuttle" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab17edba38d63047f46780cf7360acf7467fec2c048928689a5c1dd1c2b4e31" +dependencies = [ + "assoc", + "bitvec", + "cfg-if", + "generator", + "hex", + "owo-colors", + "rand 0.8.8", + "rand_core 0.6.4", + "rand_pcg", + "scoped-tls", + "smallvec", + "tracing", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -2388,6 +4077,47 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest", + "rand_core 0.10.1", +] + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "simsimd" +version = "6.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fb3bc3cdce07a7d7d4caa4c54f8aa967f6be41690482b54b24100a2253fa70" +dependencies = [ + "cc", +] + +[[package]] +name = "siphasher" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" + [[package]] name = "sketches-ddsketch" version = "0.3.1" @@ -2416,6 +4146,104 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "softaes" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4fdfe13e1c42e45f497416afb8dc4e783bf0e25b7be9077c1c77c5fb14cb998" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" +dependencies = [ + "base64ct", + "der 0.8.2", +] + +[[package]] +name = "sqlite-wasm-rs" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] + +[[package]] +name = "sqlx-core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb" +dependencies = [ + "base64 0.22.1", + "bytes", + "cfg-if", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.16.1", + "hashlink 0.11.1", + "indexmap", + "log", + "memchr", + "percent-encoding", + "rustls", + "smallvec", + "thiserror", + "time", + "tokio", + "tokio-stream", + "tracing", + "url", + "webpki-roots", +] + +[[package]] +name = "sqlx-mysql" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27" +dependencies = [ + "bitflags 2.13.1", + "byteorder", + "bytes", + "digest", + "dotenvy", + "either", + "futures-core", + "futures-util", + "generic-array", + "log", + "percent-encoding", + "rand 0.10.3", + "rsa", + "sha1", + "sha2", + "sqlx-core", + "thiserror", + "time", + "tracing", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -2427,16 +4255,14 @@ name = "steep-server" version = "1.3.0" dependencies = [ "anyhow", - "apalis", - "apalis-redis", "axum", "devcontainer-rs", "dotenvy", "futures-util", "hex", + "jiff", "metrics", "metrics-exporter-prometheus", - "redis", "reqwest", "ring", "sentry", @@ -2445,6 +4271,8 @@ dependencies = [ "serde_json", "tempfile", "thiserror", + "toasty", + "toasty-cli", "tokio", "tokio-util", "tower", @@ -2453,6 +4281,57 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.119", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + [[package]] name = "syn" version = "2.0.119" @@ -2495,6 +4374,12 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tar" version = "0.4.46" @@ -2513,9 +4398,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", - "rustix", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -2585,9 +4470,212 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" + +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "toasty" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c0ad66cbf23d9aeff0d85404e3799788dcea052d835997ed7e85bb3773725c" +dependencies = [ + "async-trait", + "bit-set", + "by_address", + "deadpool", + "hashbrown 0.17.1", + "index_vec", + "indexmap", + "inventory", + "jiff", + "serde", + "serde_core", + "serde_json", + "toasty-core", + "toasty-driver-mysql", + "toasty-driver-postgresql", + "toasty-driver-sqlite", + "toasty-driver-turso", + "toasty-macros", + "tokio", + "tokio-stream", + "toml", + "toml_edit", + "tracing", + "uuid", +] + +[[package]] +name = "toasty-cli" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756d16e2809ceaad4e2e78c0f65f7241160951648574435b331ec8ec50735cbd" +dependencies = [ + "anyhow", + "clap", + "console", + "dialoguer", + "hashbrown 0.17.1", + "jiff", + "rand 0.10.3", + "serde", + "toasty", + "toasty-core", + "toml", +] + +[[package]] +name = "toasty-core" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ce722358481c0ad55b7b5edaaf9d0669ee5de6e9c737a73ca4c27621003732" +dependencies = [ + "async-trait", + "bit-set", + "fluent-uri", + "form_urlencoded", + "hashbrown 0.17.1", + "heck", + "indexmap", + "jiff", + "percent-encoding", + "serde", + "tokio-stream", + "toml", + "tracing", + "uuid", +] + +[[package]] +name = "toasty-driver-mysql" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa5622479dff74a1db2178c8475e014f32ab434ffb06c8cb69142b0abebd876" +dependencies = [ + "async-trait", + "jiff", + "sqlx-core", + "sqlx-mysql", + "time", + "toasty-core", + "toasty-sql", + "tokio", + "tracing", + "uuid", +] + +[[package]] +name = "toasty-driver-postgresql" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cdb083715b23faddc3b667151cfda8b02feac02e0066acd933d8f8028fce4c" +dependencies = [ + "async-trait", + "fallible-iterator 0.2.0", + "hashbrown 0.17.1", + "jiff", + "lru", + "postgres-protocol", + "postgres-types", + "rustls", + "rustls-pemfile", + "rustls-platform-verifier", + "rustls-webpki", + "toasty-core", + "toasty-sql", + "tokio", + "tokio-postgres", + "tokio-postgres-rustls", + "tracing", + "uuid", +] + +[[package]] +name = "toasty-driver-sqlite" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffaebb64e79526666cb2628a7de5979da5ef282bb3f36a7e3b6a5acc55936794" +dependencies = [ + "async-trait", + "rusqlite", + "serde", + "toasty-core", + "toasty-sql", + "tracing", + "uuid", +] + +[[package]] +name = "toasty-driver-turso" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f3d4680ddf5e6ec2ba584ec91763420b572d0d818e10ca105a85d312d6f10a" +dependencies = [ + "async-trait", + "serde", + "toasty-core", + "toasty-sql", + "tokio", + "tracing", + "turso", + "uuid", +] + +[[package]] +name = "toasty-macros" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5b5a87266b1cccdd184244733b26fdac9ed3997446c5aca88c2c71f5b03f61" +dependencies = [ + "heck", + "indexmap", + "pluralizer", + "proc-macro2", + "quote", + "syn 3.0.4", + "toasty-core", +] + +[[package]] +name = "toasty-sql" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b50cee2799bc54257ba202a9497f07b59df7e446b6df27fbf801cffe4b1b8a" +dependencies = [ + "jiff", + "serde", + "serde_json", + "toasty-core", +] + [[package]] name = "tokio" version = "1.53.1" @@ -2626,6 +4714,56 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-postgres" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a528f7d280f6d5b9cd149635c8705b0dd049754bc67d81d31fa25169a93809d3" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator 0.2.0", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand 0.10.3", + "socket2", + "tokio", + "tokio-util", + "whoami", +] + +[[package]] +name = "tokio-postgres-rustls" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2ad44aa0ae96db89c4742212ed41645b2f597311ff6e1945542a4d9fadc2fb" +dependencies = [ + "rustls", + "sha2", + "tokio", + "tokio-postgres", + "tokio-rustls", + "x509-cert", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.19" @@ -2651,6 +4789,60 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "1.1.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[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.25.15+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + [[package]] name = "tower" version = "0.5.3" @@ -2662,7 +4854,6 @@ dependencies = [ "pin-project-lite", "sync_wrapper", "tokio", - "tokio-util", "tower-layer", "tower-service", "tracing", @@ -2674,7 +4865,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags", + "bitflags 2.13.1", "bytes", "futures-util", "http 1.5.0", @@ -2692,7 +4883,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08a05a66a4fdd61cbbe0a1d755ffe0ca6aba159dd4820936a0ff8a8278245b9c" dependencies = [ - "bitflags", + "bitflags 2.13.1", "bytes", "http 1.5.0", "http-body", @@ -2727,6 +4918,19 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" +dependencies = [ + "crossbeam-channel", + "symlink", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.31" @@ -2748,15 +4952,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -2793,15 +4988,211 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "ulid" -version = "1.2.1" +name = "turso" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" +checksum = "f9491d7a80312c5abe66a4409e4dce02065503a235453c94b9e4133877e39ffc" dependencies = [ - "rand", - "web-time", + "thiserror", + "tracing", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit", + "turso_sync_sdk_kit", ] +[[package]] +name = "turso_core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a833cc3bf8d4e6c101c504fa470f8ab4270c2202ff2591b61b2e373b4f20d9b" +dependencies = [ + "aegis", + "aes", + "aes-gcm", + "allocator-api2 0.4.0", + "antithesis_sdk", + "arc-swap", + "aristo", + "bigdecimal", + "bitflags 2.13.1", + "branches", + "bumpalo", + "bytemuck", + "cfg_aliases", + "cfg_block", + "chrono", + "crc32c", + "crossbeam-epoch", + "crossbeam-utils", + "either", + "fallible-iterator 0.3.0", + "fastbloom", + "hex", + "icu_collator", + "icu_locale", + "intrusive-collections", + "io-uring", + "libc", + "libloading", + "libm", + "loom", + "miette", + "num-bigint", + "num-traits", + "pack1", + "parking_lot", + "pastey", + "polling", + "rand 0.9.5", + "rapidhash", + "regex", + "regex-syntax", + "roaring", + "rustc-hash 2.1.3", + "rustix 1.1.4", + "ryu", + "serde_json", + "shuttle", + "simsimd", + "smallvec", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "tracing", + "tracing-subscriber", + "turso_ext", + "turso_macros", + "turso_parser", + "twox-hash", + "uncased", + "uuid", + "windows-sys 0.61.2", +] + +[[package]] +name = "turso_ext" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7452fe676450b6840e9eb80e512d14293265221154eba66aba3845dfc0d659f" +dependencies = [ + "chrono", + "getrandom 0.4.3", + "turso_macros", +] + +[[package]] +name = "turso_macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2825eaa6b7b893693636947f988e252c1196393fa54d4b85637c70d616d92fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "turso_parser" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e58d029f02e442df4be0b5036ce520b49c553505d9d52ef5a98fc4056e95b7" +dependencies = [ + "bitflags 2.13.1", + "memchr", + "miette", + "strum", + "strum_macros", + "thiserror", + "turso_macros", +] + +[[package]] +name = "turso_sdk_kit" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18c1dc1c0304348c39b97bc6b27cdcb1d7292454ebd0de0f30b5ee3a4c61f9bb" +dependencies = [ + "bindgen", + "env_logger", + "parking_lot", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_ext", + "turso_sdk_kit_macros", +] + +[[package]] +name = "turso_sdk_kit_macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4708b5fe678b8730c85964e3d378f75e18c23c4409971360b2209f4e53e4956" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "turso_sync_engine" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8f03e430240d590d209ac874db52773b7382c627cd604a685affde77622b09" +dependencies = [ + "base64 0.22.1", + "bytes", + "crc32c", + "genawaiter", + "http 1.5.0", + "libc", + "prost", + "roaring", + "serde", + "serde_json", + "thiserror", + "tracing", + "turso_core", + "turso_parser", + "uuid", +] + +[[package]] +name = "turso_sync_sdk_kit" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cb47d056c3ec567745761fa6f832358ca30ef9eb0435fdcfb77c558e70089" +dependencies = [ + "bindgen", + "env_logger", + "genawaiter", + "parking_lot", + "tracing", + "tracing-appender", + "tracing-subscriber", + "turso_core", + "turso_sdk_kit", + "turso_sdk_kit_macros", + "turso_sync_engine", +] + +[[package]] +name = "twox-hash" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86a801b3cea342a06d468c8710662aa29e5e05e4f5c0d62f00bbb7f2ad7941c2" +dependencies = [ + "rand 0.10.3", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + [[package]] name = "uname" version = "0.1.1" @@ -2811,24 +5202,76 @@ dependencies = [ "libc", ] +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-segmentation" version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common 0.1.7", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2842,7 +5285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d" dependencies = [ "base64 0.23.1", - "der", + "der 0.8.2", "log", "native-tls", "percent-encoding", @@ -2877,6 +5320,12 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + [[package]] name = "utf8-zero" version = "0.8.1" @@ -2889,14 +5338,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" dependencies = [ + "getrandom 0.4.3", "js-sys", + "rand 0.10.3", "serde_core", + "sha1_smol", "wasm-bindgen", ] @@ -2912,6 +5370,22 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2927,6 +5401,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + [[package]] name = "wasip2" version = "1.0.4+wasi-0.2.12" @@ -2936,6 +5419,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" +dependencies = [ + "wasi 0.14.7+wasi-0.2.4", +] + [[package]] name = "wasm-bindgen" version = "0.2.127" @@ -3014,16 +5506,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-root-certs" version = "1.0.9" @@ -3033,6 +5515,40 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "whoami" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c" +dependencies = [ + "libc", + "libredox", + "objc2-system-configuration", + "wasite", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3049,6 +5565,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3196,18 +5721,54 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + [[package]] name = "writeable" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid 0.9.6", + "der 0.7.10", + "spki 0.7.3", + "tls_codec", +] + [[package]] name = "xattr" version = "1.6.1" @@ -3215,7 +5776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix", + "rustix 1.1.4", ] [[package]] @@ -3287,6 +5848,20 @@ name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] name = "zerotrie" @@ -3297,6 +5872,7 @@ dependencies = [ "displaydoc", "yoke", "zerofrom", + "zerovec", ] [[package]] @@ -3305,6 +5881,7 @@ version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", diff --git a/Cargo.toml b/Cargo.toml index ee4b5e9..2302f99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,9 +28,9 @@ hex = "0.4" bytes = "1.1" metrics = "0.24" metrics-exporter-prometheus = { version = "0.18", default-features = false, features = ["http-listener"] } -apalis = { version = "0.7", features = ["catch-panic", "limit"] } -apalis-redis = "0.7" -redis = { version = "0.32", features = ["tokio-comp", "connection-manager"] } +toasty = { version = "0.11", features = ["postgresql", "serde", "jiff"] } +toasty-cli = "0.11" +jiff = "0.2" [profile.release] debug = 1 diff --git a/Containerfile b/Containerfile index ccb90f5..c2a086e 100644 --- a/Containerfile +++ b/Containerfile @@ -10,10 +10,7 @@ RUN cargo build --release --package steep-server FROM debian:trixie-slim -# git clones the pull request. ca-certificates is what every HTTPS call needs -# (Gitea, OpenRouter, git). The shared libraries are the non-base ones the binary -# links against, as reported by `ldd target/release/steep-server`; libc, libm -# and libgcc_s come from the base image. + RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ git \ @@ -26,6 +23,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /app COPY --from=builder /app/target/release/steep-server ./steep-server -# Exec form, so the binary is PID 1 and receives the SIGTERM it handles to shut -# down gracefully. -CMD ["./steep-server"] +COPY crates/steep-server/toasty ./toasty +ENV MIGRATIONS_DIR=/app/toasty + +CMD ["sh", "-c", "./steep-server migration apply && exec ./steep-server"] diff --git a/README.md b/README.md index 7a35eaf..62f20b1 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Steep reads its configuration from environment variables (a `.env` file is suppo | `GITEA_URL` | Base URL of your Gitea instance | | `GITEA_TOKEN` | Gitea API token | | `GITEA_TIMEOUT` | Gitea API request timeout in seconds | -| `REDIS_URL` | Redis connection URL used for the durable review queue (e.g. `redis://127.0.0.1:6379`) | +| `DATABASE_URL` | PostgreSQL connection URL used for the durable review queue (e.g. `postgresql://user:pass@localhost:5432/steep`) | | `METRICS_BIND_ADDR` | *(optional)* Bind address for the Prometheus metrics endpoint (e.g. `0.0.0.0:9100`). If unset, the metrics exporter is disabled. | | `SENTRY_DSN` | *(optional)* Sentry DSN for error tracking | | `RUST_LOG` | *(optional)* Log level, defaults to `info` | @@ -102,6 +102,26 @@ hooks have run, the container is disconnected from the network for the rest of the review. Every container command is bounded by a timeout, and the container, network and image are removed when the review ends (including on failure). +## Migrations + +The database schema is versioned with [Toasty](https://github.com/tokio-rs/toasty) migrations, stored in `crates/steep-server/toasty/` (commit them). + +After changing a model in `crates/steep-server/src/schemas/`, generate a migration: + +```sh +cargo run -p steep-server -- migration generate --name describe_change +``` + +Apply the pending migrations **before starting the service** — the server does not migrate at boot: + +```sh +cargo run -p steep-server -- migration apply +``` + +The `Containerfile` does this at startup: its entrypoint runs `steep-server migration apply` before exec'ing the server. The CLI reads the migration files from `MIGRATIONS_DIR` (defaults to the crate's `toasty/` directory; the image sets it to `/app/toasty`). + +Other subcommands: `migration snapshot`, `migration drop`, `migration reset`. They read `DATABASE_URL`. + ## Development The easiest way to get started is with the provided [Dev Container](https://containers.dev/) (VS Code or Zed with the dev container extension). @@ -129,7 +149,7 @@ Set `METRICS_BIND_ADDR` (e.g. `0.0.0.0:9100`) to enable it. The metrics are then |---|---|---| | `steep_webhooks_received_total` | counter | Total webhooks received (label: `event_type`) | | `steep_webhooks_duplicate_total` | counter | Webhooks rejected as duplicates (label: `event_type`) | -| `steep_webhooks_enqueue_failed_total` | counter | Webhooks dropped because enqueueing to Redis failed (label: `event_type`) | +| `steep_webhooks_enqueue_failed_total` | counter | Webhooks dropped because enqueueing to PostgreSQL failed (label: `event_type`) | | `steep_bot_tasks_active` | gauge | Bot tasks currently in progress | | `steep_bot_tasks_skipped_total` | counter | Reviews skipped because they were already done (label: `event_type`) | | `steep_bot_tasks_completed_total` | counter | Bot tasks completed successfully (label: `event_type`) | diff --git a/crates/steep-server/Cargo.toml b/crates/steep-server/Cargo.toml index b6a466a..bd12c40 100644 --- a/crates/steep-server/Cargo.toml +++ b/crates/steep-server/Cargo.toml @@ -26,6 +26,6 @@ metrics = { workspace = true } metrics-exporter-prometheus = { workspace = true } devcontainer-rs = { path = "../devcontainer-rs" } tempfile = "3" -apalis = { workspace = true } -apalis-redis = { workspace = true } -redis = { workspace = true } +toasty = { workspace = true } +toasty-cli = { workspace = true } +jiff = { workspace = true } diff --git a/crates/steep-server/src/api.rs b/crates/steep-server/src/api.rs index 844c4ba..4896016 100644 --- a/crates/steep-server/src/api.rs +++ b/crates/steep-server/src/api.rs @@ -14,10 +14,7 @@ use tracing::{info, instrument}; use tokio_util::sync::CancellationToken; -use apalis::prelude::Storage; - use crate::consts::{GITEA_EVENT_TYPE_HEADER_NAME, GITEA_SIG_HEADER_NAME, MAX_WEBHOOK_BODY_SIZE}; -use crate::dedup::{Dedup, WEBHOOK_TTL}; use crate::errors::AppError; use crate::gitea::WebhookType; use crate::metrics; @@ -64,20 +61,19 @@ async fn webhook( metrics::webhook_received(event_type); let event_id = wb.event_id(); - let webhook_key = Dedup::webhook_key(event_id); - if !app_state - .dedup - .claim(&webhook_key, WEBHOOK_TTL) - .await - .map_err(anyhow::Error::from)? - { - metrics::webhook_duplicate(event_type); - return Err(AppError::AlreadyProcessedErr); + match app_state.dedup.is_known(event_id).await { + Ok(true) => { + metrics::webhook_duplicate(event_type); + return Err(AppError::AlreadyProcessedErr); + } + Ok(false) => {} + Err(err) => { + metrics::webhook_enqueue_failed(event_type); + return Err(AppError::EnqueueErr(anyhow::Error::from(err))); + } } - let mut storage = app_state.storage.clone(); - if let Err(err) = storage.push(wb).await { - app_state.dedup.release(&webhook_key).await.ok(); + if let Err(err) = app_state.queue.push(wb).await { metrics::webhook_enqueue_failed(event_type); return Err(AppError::EnqueueErr(anyhow::Error::from(err))); } diff --git a/crates/steep-server/src/bot.rs b/crates/steep-server/src/bot.rs index fdb8c1c..dadc2f2 100644 --- a/crates/steep-server/src/bot.rs +++ b/crates/steep-server/src/bot.rs @@ -1,15 +1,21 @@ +use std::sync::Arc; + +use futures_util::StreamExt; +use serde::{Deserialize, Deserializer}; +use tokio::sync::Semaphore; +use tokio_util::sync::CancellationToken; +use tracing::{error, info, instrument}; + use crate::{ - dedup::{Dedup, REVIEW_TTL}, + bot_actions::review::ReviewOutcome, + dedup::{Dedup, ReviewRecord}, gitea::{GiteaAPI, WebhookType}, + job_queue::JobQueue, metrics, open_router::OpenRouterClient, sandbox::SandboxConfig, + schemas::Job, }; -use apalis::prelude::{Data, Error, Monitor, WorkerBuilder, WorkerBuilderExt, WorkerFactoryFn}; -use apalis_redis::RedisStorage; -use serde::{Deserialize, Deserializer}; -use tokio_util::sync::CancellationToken; -use tracing::{error, info, instrument}; #[derive(Deserialize, Debug)] pub struct ReviewResult { @@ -127,6 +133,7 @@ pub struct Bot { open_router_model: String, sandbox: SandboxConfig, dedup: Dedup, + queue: JobQueue, } impl Bot { @@ -137,6 +144,7 @@ impl Bot { open_router_model: String, sandbox: SandboxConfig, dedup: Dedup, + queue: JobQueue, ) -> Self { Self { gitea_api, @@ -145,40 +153,119 @@ impl Bot { open_router_model, sandbox, dedup, + queue, } } - /// Consomme la file Redis jusqu'à l'annulation de `shutdown`. + /// Consomme la file jusqu'à l'annulation de `shutdown`. /// - /// Les jobs en cours sont laissés se terminer, et ceux qui n'ont pas encore - /// été acquittés restent dans Redis : ils seront repris au prochain démarrage. - pub async fn start( - &self, - storage: RedisStorage, - shutdown: CancellationToken, - ) -> anyhow::Result<()> { + /// Un sémaphore borne la concurrence ; les jobs en cours sont laissés se + /// terminer. Les jobs non terminés restent en base et seront repris au + /// prochain démarrage. + pub async fn start(&self, shutdown: CancellationToken) -> anyhow::Result<()> { info!("Bot started"); - let worker = WorkerBuilder::new("steep-review") - .concurrency(self.max_concurrent) - .data(self.clone()) - .backend(storage) - .build_fn(handle_review); + let semaphore = Arc::new(Semaphore::new(self.max_concurrent)); + let mut tasks = tokio::task::JoinSet::new(); + let mut pending = std::pin::pin!(self.queue.pending()); - Monitor::new() - .register(worker) - .run_with_signal(async move { - shutdown.cancelled().await; - Ok(()) - }) - .await?; + loop { + let job = tokio::select! { + biased; + _ = shutdown.cancelled() => break, + job = pending.next() => match job { + Some(job) => job, + None => break, + }, + }; + + while let Some(res) = tasks.try_join_next() { + if let Err(err) = res { + error!("Task panicked: {err}"); + } + } + + let permit = semaphore.clone().acquire_owned().await?; + + if let Err(err) = self.queue.mark_processing(job.id).await { + error!(%err, "failed to mark job as processing"); + } + + let bot = self.clone(); + metrics::increment_task_active(); + + tasks.spawn(async move { + bot.process(job).await; + drop(permit); + metrics::decrement_task_active(); + }); + } + + tasks.join_all().await; info!("Bot shutting down complete"); Ok(()) } + async fn process(&self, job: Job) { + let event_type = job.payload.event_type_str(); + + match self.dedup.is_reviewed(job.event_id).await { + Ok(true) => { + metrics::task_skipped(event_type); + info!("Review already done, skipping"); + + if let Err(err) = self.queue.remove(job.id).await { + error!(%err, "failed to remove job"); + } + return; + } + Ok(false) => {} + Err(err) => error!(%err, "Dedup lookup failed, reviewing anyway"), + } + + let payload = job.payload.0.clone(); + let started = std::time::Instant::now(); + let result = self.exec(payload).await; + let duration_ms = started.elapsed().as_millis() as u64; + + let (ok, outcome) = match result { + Ok(outcome) => { + metrics::task_completed(event_type); + info!("Task completed"); + (true, outcome) + } + Err(err) => { + metrics::task_failed(event_type); + error!(%err, "Task error"); + sentry_anyhow::capture_anyhow(&err); + (false, ReviewOutcome::empty()) + } + }; + + let record = ReviewRecord { + event_id: job.event_id, + repo: job.repo.clone(), + pr: job.pr, + ok, + model: self.open_router_model.clone(), + markdown: outcome.markdown, + cost: outcome.cost, + comments: outcome.comments as u64, + duration_ms, + }; + + if let Err(err) = self.dedup.mark_reviewed(record).await { + error!(%err, "failed to record review"); + } + + if let Err(err) = self.queue.remove(job.id).await { + error!(%err, "failed to remove job"); + } + } + #[instrument(skip(self, webhook), fields(repo, pr))] - pub async fn exec(&self, webhook: WebhookType) -> anyhow::Result<()> { + pub async fn exec(&self, webhook: WebhookType) -> anyhow::Result { match &webhook { WebhookType::Review(p) => { tracing::Span::current().record("repo", &p.repository.full_name); @@ -203,40 +290,3 @@ impl Bot { } } } - -async fn handle_review(webhook: WebhookType, bot: Data) -> Result<(), Error> { - let event_type = webhook.event_type_str(); - let review_key = Dedup::review_key(webhook.event_id()); - - match bot.dedup.is_marked(&review_key).await { - Ok(true) => { - metrics::task_skipped(event_type); - info!("Review already done, skipping"); - return Ok(()); - } - Ok(false) => {} - Err(err) => error!(%err, "Dedup lookup failed, reviewing anyway"), - } - - metrics::increment_task_active(); - let result = bot.exec(webhook).await; - metrics::decrement_task_active(); - - match result { - Ok(()) => { - metrics::task_completed(event_type); - info!("Task completed"); - - if let Err(err) = bot.dedup.mark(&review_key, REVIEW_TTL).await { - error!(%err, "Failed to mark review as done"); - } - } - Err(err) => { - metrics::task_failed(event_type); - error!(%err, "Task error"); - sentry_anyhow::capture_anyhow(&err); - } - } - - Ok(()) -} diff --git a/crates/steep-server/src/bot_actions/review.rs b/crates/steep-server/src/bot_actions/review.rs index e0ac54f..e37cf08 100644 --- a/crates/steep-server/src/bot_actions/review.rs +++ b/crates/steep-server/src/bot_actions/review.rs @@ -12,6 +12,22 @@ use crate::{ text::excerpt, }; +pub struct ReviewOutcome { + pub markdown: String, + pub cost: Option, + pub comments: usize, +} + +impl ReviewOutcome { + pub fn empty() -> Self { + Self { + markdown: String::new(), + cost: None, + comments: 0, + } + } +} + #[instrument(skip(gitea_api, open_router_client, sandbox_config, tools, review_payload))] pub async fn exec_review( gitea_api: &GiteaAPI, @@ -20,7 +36,7 @@ pub async fn exec_review( sandbox_config: &SandboxConfig, tools: Vec, review_payload: ReviewPayload, -) -> anyhow::Result<()> { +) -> anyhow::Result { tracing::info!( repo = %review_payload.repository.full_name, pr = review_payload.pull_request.number, @@ -36,7 +52,7 @@ pub async fn exec_review( ) .await?; - let bot_result: Result = async { + let bot_result: Result<(ReviewResult, String), anyhow::Error> = async { let full_name = &review_payload.repository.full_name; let index = review_payload.pull_request.number; @@ -91,15 +107,21 @@ pub async fn exec_review( ) .await?; - Ok(review_result) + Ok((review_result, final_review_markdown)) } .await; match bot_result { - Ok(_) => { + Ok((review_result, markdown)) => { gitea_api .delete_comment(&review_payload.repository.full_name, new_comment.id) - .await + .await?; + + Ok(ReviewOutcome { + markdown, + cost: review_result.cost, + comments: review_result.reviews.len(), + }) } Err(e) => { gitea_api @@ -108,17 +130,13 @@ pub async fn exec_review( &review_payload.repository.full_name, new_comment.id, ) - .await + .await?; + + Err(e) } } } -/// Runs the review inside a sandbox container, letting the model explore the -/// repository with tools before answering. -/// -/// The answer of the model is parsed by [`ReviewResult::from_str`], which the -/// agent loop enforces: an answer that is not a review is sent back to the model -/// for correction. async fn run_sandboxed_review( gitea_api: &GiteaAPI, open_router_client: &OpenRouterClient, diff --git a/crates/steep-server/src/db.rs b/crates/steep-server/src/db.rs new file mode 100644 index 0000000..2eb62e6 --- /dev/null +++ b/crates/steep-server/src/db.rs @@ -0,0 +1,43 @@ +use toasty::Db; + +use crate::schemas::{Job, JobStatus}; + +pub async fn open(url: &str) -> toasty::Result { + Db::builder() + .models(toasty::models!(crate::*)) + .connect(url) + .await +} + +pub async fn connect(url: &str) -> toasty::Result { + let mut db = open(url).await?; + + Job::update_by_status(JobStatus::Processing) + .status(JobStatus::Pending) + .exec(&mut db) + .await?; + + Ok(db) +} + +#[cfg(test)] +pub(crate) async fn test_connect() -> Db { + static DB: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); + + DB.get_or_init(|| async { + let url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + + let migrations = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("toasty"); + let config = toasty_cli::Config::new() + .migration(toasty_cli::MigrationConfig::new().path(migrations)); + + toasty_cli::ToastyCli::with_config(open(&url).await.expect("open pool"), config) + .parse_from(["toasty", "migration", "apply"]) + .await + .expect("apply migrations"); + + connect(&url).await.expect("connect to postgres") + }) + .await + .clone() +} diff --git a/crates/steep-server/src/dedup.rs b/crates/steep-server/src/dedup.rs index b414859..b3d83af 100644 --- a/crates/steep-server/src/dedup.rs +++ b/crates/steep-server/src/dedup.rs @@ -1,66 +1,71 @@ -use std::time::Duration; +use toasty::Db; -use redis::aio::ConnectionManager; +use crate::schemas::{Job, Review}; -pub const WEBHOOK_TTL: Duration = Duration::from_secs(24 * 60 * 60); -pub const REVIEW_TTL: Duration = Duration::from_secs(7 * 24 * 60 * 60); +pub struct ReviewRecord { + pub event_id: u64, + pub repo: String, + pub pr: u64, + pub ok: bool, + pub model: String, + pub markdown: String, + pub cost: Option, + pub comments: u64, + pub duration_ms: u64, +} #[derive(Clone)] pub struct Dedup { - conn: ConnectionManager, + db: Db, } impl Dedup { - pub fn new(conn: ConnectionManager) -> Self { - Self { conn } + pub fn new(db: Db) -> Self { + Self { db } } - pub fn webhook_key(event_id: u64) -> String { - format!("steep:webhook:{event_id}") + pub async fn is_known(&self, event_id: u64) -> toasty::Result { + let mut db = self.db.clone(); + + if Job::filter_by_event_id(event_id) + .first() + .exec(&mut db) + .await? + .is_some() + { + return Ok(true); + } + + Ok(Review::filter_by_event_id(event_id) + .first() + .exec(&mut db) + .await? + .is_some()) } - pub fn review_key(event_id: u64) -> String { - format!("steep:review:{event_id}") + pub async fn is_reviewed(&self, event_id: u64) -> toasty::Result { + let mut db = self.db.clone(); + + Ok(Review::filter_by_event_id(event_id) + .first() + .exec(&mut db) + .await? + .is_some()) } - pub async fn claim(&self, key: &str, ttl: Duration) -> redis::RedisResult { - let set: Option = redis::cmd("SET") - .arg(key) - .arg(1) - .arg("NX") - .arg("EX") - .arg(ttl.as_secs()) - .query_async(&mut self.conn.clone()) - .await?; + pub async fn mark_reviewed(&self, record: ReviewRecord) -> toasty::Result<()> { + let mut db = self.db.clone(); - Ok(set.is_some()) - } - - pub async fn mark(&self, key: &str, ttl: Duration) -> redis::RedisResult<()> { - let _: String = redis::cmd("SET") - .arg(key) - .arg(1) - .arg("EX") - .arg(ttl.as_secs()) - .query_async(&mut self.conn.clone()) - .await?; - - Ok(()) - } - - pub async fn is_marked(&self, key: &str) -> redis::RedisResult { - let exists: i64 = redis::cmd("EXISTS") - .arg(key) - .query_async(&mut self.conn.clone()) - .await?; - - Ok(exists > 0) - } - - pub async fn release(&self, key: &str) -> redis::RedisResult<()> { - let _: i64 = redis::cmd("DEL") - .arg(key) - .query_async(&mut self.conn.clone()) + Review::upsert_by_event_id(record.event_id) + .repo(record.repo) + .pr(record.pr) + .ok(record.ok) + .model(record.model) + .markdown(record.markdown) + .cost(record.cost) + .comments(record.comments) + .duration_ms(record.duration_ms) + .exec(&mut db) .await?; Ok(()) @@ -70,51 +75,42 @@ impl Dedup { #[cfg(test)] mod tests { use super::*; - - #[test] - fn webhook_key_is_namespaced() { - assert_eq!(Dedup::webhook_key(42), "steep:webhook:42"); - } - - #[test] - fn review_key_is_namespaced() { - assert_eq!(Dedup::review_key(42), "steep:review:42"); - } - - #[test] - fn the_two_keys_for_the_same_event_differ() { - assert_ne!(Dedup::webhook_key(7), Dedup::review_key(7)); - } - - async fn redis_dedup() -> Dedup { - let url = std::env::var("REDIS_URL").expect("REDIS_URL must be set"); - Dedup::new(apalis_redis::connect(url).await.expect("connect to redis")) - } + use crate::schemas::Review; #[tokio::test] - #[ignore = "requires a running Redis (REDIS_URL)"] - async fn claim_then_claim_is_a_duplicate() { - let dedup = redis_dedup().await; - let key = "steep:test:claim"; - dedup.release(key).await.unwrap(); + #[ignore = "requires DATABASE_URL"] + async fn a_recorded_review_is_known_and_reviewed() { + let db = crate::db::test_connect().await; + let dedup = Dedup::new(db.clone()); - assert!(dedup.claim(key, Duration::from_secs(30)).await.unwrap()); - assert!(!dedup.claim(key, Duration::from_secs(30)).await.unwrap()); + let event_id = 999_000_101; + Review::delete_by_event_id(&mut db.clone(), event_id) + .await + .ok(); - dedup.release(key).await.unwrap(); - } + assert!(!dedup.is_known(event_id).await.unwrap()); + assert!(!dedup.is_reviewed(event_id).await.unwrap()); - #[tokio::test] - #[ignore = "requires a running Redis (REDIS_URL)"] - async fn mark_then_is_marked() { - let dedup = redis_dedup().await; - let key = "steep:test:mark"; - dedup.release(key).await.unwrap(); + dedup + .mark_reviewed(ReviewRecord { + event_id, + repo: "owner/repo".to_string(), + pr: 1, + ok: true, + model: "test/model".to_string(), + markdown: "looks good".to_string(), + cost: Some(0.01), + comments: 2, + duration_ms: 5, + }) + .await + .unwrap(); - assert!(!dedup.is_marked(key).await.unwrap()); - dedup.mark(key, Duration::from_secs(30)).await.unwrap(); - assert!(dedup.is_marked(key).await.unwrap()); + assert!(dedup.is_reviewed(event_id).await.unwrap()); + assert!(dedup.is_known(event_id).await.unwrap()); - dedup.release(key).await.unwrap(); + Review::delete_by_event_id(&mut db.clone(), event_id) + .await + .unwrap(); } } diff --git a/crates/steep-server/src/env.rs b/crates/steep-server/src/env.rs index 771c490..adf1973 100644 --- a/crates/steep-server/src/env.rs +++ b/crates/steep-server/src/env.rs @@ -11,7 +11,7 @@ pub struct EnvConfig { pub gitea_url: String, pub gitea_token: String, pub gitea_timeout: u64, - pub redis_url: String, + pub database_url: String, pub metrics_bind_addr: Option, pub sandbox_max_iterations: usize, } @@ -26,7 +26,7 @@ pub fn load_config() -> anyhow::Result { let gitea_url = try_get_env("GITEA_URL")?; let gitea_token = try_get_env("GITEA_TOKEN")?; let gitea_timeout = try_get_env("GITEA_TIMEOUT")?.parse()?; - let redis_url = try_get_env("REDIS_URL")?; + let database_url = try_get_env("DATABASE_URL")?; let metrics_bind_addr = std::env::var("METRICS_BIND_ADDR").ok(); let sandbox_max_iterations = std::env::var("SANDBOX_MAX_ITERATIONS") .ok() @@ -43,7 +43,7 @@ pub fn load_config() -> anyhow::Result { gitea_url, gitea_token, gitea_timeout, - redis_url, + database_url, metrics_bind_addr, sandbox_max_iterations, }) diff --git a/crates/steep-server/src/gitea.rs b/crates/steep-server/src/gitea.rs index e3e3112..d1616f3 100644 --- a/crates/steep-server/src/gitea.rs +++ b/crates/steep-server/src/gitea.rs @@ -281,7 +281,7 @@ async fn read_capped(response: reqwest::Response) -> anyhow::Result { Ok(String::from_utf8_lossy(&buf).into_owned()) } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub enum WebhookType { Review(ReviewPayload), } @@ -298,9 +298,21 @@ impl WebhookType { WebhookType::Review(_) => "review", } } + + pub fn repository_full_name(&self) -> &str { + match self { + WebhookType::Review(payload) => &payload.repository.full_name, + } + } + + pub fn pull_request_number(&self) -> u64 { + match self { + WebhookType::Review(payload) => payload.pull_request.number, + } + } } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct ReviewPayload { pub action: String, pub pull_request: PullRequest, @@ -308,13 +320,13 @@ pub struct ReviewPayload { pub comment: Comment, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct PullRequest { pub number: u64, pub title: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct Comment { pub id: u64, pub body: String, @@ -325,7 +337,7 @@ pub struct User { pub login: String, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct Repository { pub full_name: String, pub clone_url: String, diff --git a/crates/steep-server/src/job_queue.rs b/crates/steep-server/src/job_queue.rs new file mode 100644 index 0000000..d09649d --- /dev/null +++ b/crates/steep-server/src/job_queue.rs @@ -0,0 +1,196 @@ +use std::{collections::VecDeque, time::Duration}; + +use futures_util::stream::{self, Stream}; +use toasty::Db; +use tracing::error; + +use crate::{ + gitea::WebhookType, + schemas::{Job, JobStatus}, +}; + +/// Délai entre deux interrogations de la table quand la file est vide. +const POLL_INTERVAL: Duration = Duration::from_secs(1); + +/// File des reviews à faire. +#[derive(Clone)] +pub struct JobQueue { + db: Db, +} + +impl JobQueue { + pub fn new(db: Db) -> Self { + Self { db } + } + + /// Enfile une nouvelle review. + /// + /// L'unicité de `event_id` fait échouer l'insertion d'un doublon. + pub async fn push(&self, webhook: WebhookType) -> toasty::Result<()> { + let event_id = webhook.event_id(); + let repo = webhook.repository_full_name().to_string(); + let pr = webhook.pull_request_number(); + + let mut db = self.db.clone(); + + toasty::create!(Job { + event_id, + repo, + pr, + payload: webhook, + status: JobStatus::Pending, + }) + .exec(&mut db) + .await?; + + Ok(()) + } + + /// Flux des jobs en attente. + /// + /// C'est un `Stream` (et non un `Iterator`) : l'accès à la base est + /// asynchrone. Le flux interroge la table en boucle et met en tampon les + /// jobs trouvés. + pub fn pending(&self) -> impl Stream { + let db = self.db.clone(); + + stream::unfold(VecDeque::new(), move |mut buffer| { + let db = db.clone(); + + async move { + let mut db = db; + + loop { + if let Some(job) = buffer.pop_front() { + return Some((job, buffer)); + } + + match Job::filter_by_status(JobStatus::Pending) + .exec(&mut db) + .await + { + Ok(jobs) if jobs.is_empty() => { + tokio::time::sleep(POLL_INTERVAL).await; + } + Ok(jobs) => buffer.extend(jobs), + Err(err) => { + error!(%err, "failed to poll pending jobs"); + tokio::time::sleep(POLL_INTERVAL).await; + } + } + } + } + }) + } + + /// Marque un job comme en cours de traitement. + pub async fn mark_processing(&self, id: u64) -> toasty::Result<()> { + let mut db = self.db.clone(); + + Job::update_by_id(id) + .status(JobStatus::Processing) + .exec(&mut db) + .await?; + + Ok(()) + } + + /// Retire un job de la file, une fois la review enregistrée. + pub async fn remove(&self, id: u64) -> toasty::Result<()> { + let mut db = self.db.clone(); + + Job::delete_by_id(&mut db, id).await?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use futures_util::StreamExt; + + use super::*; + use crate::gitea::{Comment, PullRequest, Repository, ReviewPayload}; + + fn webhook(event_id: u64) -> WebhookType { + WebhookType::Review(ReviewPayload { + action: "created".to_string(), + pull_request: PullRequest { + number: 1, + title: "Test".to_string(), + }, + repository: Repository { + full_name: "owner/repo".to_string(), + clone_url: "https://example.com/owner/repo.git".to_string(), + }, + comment: Comment { + id: event_id, + body: "@bot review".to_string(), + }, + }) + } + + async fn next_job(queue: &JobQueue, event_id: u64) -> Job { + let mut pending = std::pin::pin!(queue.pending()); + + tokio::time::timeout(Duration::from_secs(10), async { + loop { + if let Some(job) = pending.next().await + && job.event_id == event_id + { + break job; + } + } + }) + .await + .expect("timed out waiting for the job") + } + + #[tokio::test] + #[ignore = "requires DATABASE_URL"] + async fn a_pushed_job_is_pending_then_removed() { + let db = crate::db::test_connect().await; + let queue = JobQueue::new(db.clone()); + + let event_id = 999_000_201; + Job::delete_by_event_id(&mut db.clone(), event_id) + .await + .ok(); + + queue.push(webhook(event_id)).await.unwrap(); + + let job = next_job(&queue, event_id).await; + queue.mark_processing(job.id).await.unwrap(); + queue.remove(job.id).await.unwrap(); + + assert!( + Job::filter_by_event_id(event_id) + .first() + .exec(&mut db.clone()) + .await + .unwrap() + .is_none() + ); + } + + #[tokio::test] + #[ignore = "requires DATABASE_URL"] + async fn a_duplicate_event_id_is_rejected() { + let db = crate::db::test_connect().await; + let queue = JobQueue::new(db.clone()); + + let event_id = 999_000_202; + Job::delete_by_event_id(&mut db.clone(), event_id) + .await + .ok(); + + queue.push(webhook(event_id)).await.unwrap(); + assert!(queue.push(webhook(event_id)).await.is_err()); + + Job::delete_by_event_id(&mut db.clone(), event_id) + .await + .unwrap(); + } +} diff --git a/crates/steep-server/src/main.rs b/crates/steep-server/src/main.rs index 3558457..6d4231c 100644 --- a/crates/steep-server/src/main.rs +++ b/crates/steep-server/src/main.rs @@ -1,12 +1,8 @@ use std::time::Duration; use crate::{ - bot::Bot, - dedup::Dedup, - gitea::{GiteaAPI, WebhookType}, - open_router::OpenRouterClient, - sandbox::SandboxConfig, - state::AppState, + bot::Bot, dedup::Dedup, gitea::GiteaAPI, job_queue::JobQueue, open_router::OpenRouterClient, + sandbox::SandboxConfig, state::AppState, }; use dotenvy::dotenv; @@ -19,13 +15,16 @@ mod api; mod bot; mod bot_actions; mod consts; +mod db; mod dedup; mod env; mod errors; mod gitea; +mod job_queue; mod metrics; mod open_router; mod sandbox; +mod schemas; mod state; mod text; @@ -38,6 +37,11 @@ const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(60); fn main() -> anyhow::Result<()> { dotenv().ok(); + // Sous-commande de migration : `steep-server migration `. + if std::env::args().nth(1).as_deref() == Some("migration") { + return tokio::runtime::Runtime::new()?.block_on(run_migrations()); + } + tracing_subscriber::registry() .with(fmt::layer()) .with( @@ -63,6 +67,24 @@ fn main() -> anyhow::Result<()> { tokio::runtime::Runtime::new()?.block_on(run()) } +async fn run_migrations() -> anyhow::Result<()> { + let database_url = env::try_get_env("DATABASE_URL")?; + let db = db::open(&database_url).await?; + + let migrations = match std::env::var("MIGRATIONS_DIR") { + Ok(dir) => std::path::PathBuf::from(dir), + Err(_) => std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("toasty"), + }; + let config = + toasty_cli::Config::new().migration(toasty_cli::MigrationConfig::new().path(migrations)); + + toasty_cli::ToastyCli::with_config(db, config) + .parse_and_run() + .await?; + + Ok(()) +} + async fn run() -> anyhow::Result<()> { let config = env::load_config()?; @@ -101,10 +123,9 @@ async fn run() -> anyhow::Result<()> { ); } - let redis_conn = apalis_redis::connect(config.redis_url.clone()).await?; - let storage: apalis_redis::RedisStorage = - apalis_redis::RedisStorage::new(redis_conn.clone()); - let dedup = Dedup::new(redis_conn); + let db = db::connect(&config.database_url).await?; + let dedup = Dedup::new(db.clone()); + let queue = JobQueue::new(db); let bot = Bot::new( gitea_api, @@ -113,12 +134,13 @@ async fn run() -> anyhow::Result<()> { config.open_router_model.clone(), sandbox, dedup.clone(), + queue.clone(), ); let app_state = AppState { - storage: storage.clone(), - bot_name: gitea_user.login.clone(), + queue, dedup, + bot_name: gitea_user.login.clone(), config, }; @@ -143,7 +165,7 @@ async fn run() -> anyhow::Result<()> { tokio::select! { result = async { tokio::try_join!( - bot.start(storage, shutdown.clone()), + bot.start(shutdown.clone()), api::start(app_state, shutdown.clone()), signal ) diff --git a/crates/steep-server/src/metrics.rs b/crates/steep-server/src/metrics.rs index ff1771c..3f41b99 100644 --- a/crates/steep-server/src/metrics.rs +++ b/crates/steep-server/src/metrics.rs @@ -54,7 +54,7 @@ pub fn describe() { describe_counter!( "steep_webhooks_enqueue_failed_total", Unit::Count, - "Webhooks dropped because enqueueing to Redis failed" + "Webhooks dropped because enqueueing to PostgreSQL failed" ); describe_gauge!( "steep_bot_tasks_active", diff --git a/crates/steep-server/src/schemas/job.rs b/crates/steep-server/src/schemas/job.rs new file mode 100644 index 0000000..d36cf4a --- /dev/null +++ b/crates/steep-server/src/schemas/job.rs @@ -0,0 +1,31 @@ +use jiff::Timestamp; + +use crate::gitea::WebhookType; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, toasty::Embed)] +pub enum JobStatus { + Pending, + Processing, +} + +#[derive(Debug, toasty::Model)] +pub struct Job { + #[key] + #[auto] + pub id: u64, + + #[unique] + pub event_id: u64, + + pub repo: String, + pub pr: u64, + + #[column(type = jsonb)] + pub payload: toasty::Json, + + #[index] + pub status: JobStatus, + + #[auto] + pub created_at: Timestamp, +} diff --git a/crates/steep-server/src/schemas/mod.rs b/crates/steep-server/src/schemas/mod.rs new file mode 100644 index 0000000..0a80355 --- /dev/null +++ b/crates/steep-server/src/schemas/mod.rs @@ -0,0 +1,5 @@ +pub mod job; +pub mod review; + +pub use job::{Job, JobStatus}; +pub use review::Review; diff --git a/crates/steep-server/src/schemas/review.rs b/crates/steep-server/src/schemas/review.rs new file mode 100644 index 0000000..0539bfa --- /dev/null +++ b/crates/steep-server/src/schemas/review.rs @@ -0,0 +1,35 @@ +use jiff::Timestamp; + +#[derive(Debug, toasty::Model)] +pub struct Review { + #[key] + #[auto] + pub id: u64, + + #[unique] + pub event_id: u64, + + pub repo: String, + pub pr: u64, + + /// Vrai si la review a abouti. + pub ok: bool, + + /// Modèle utilisé. + pub model: String, + + /// Markdown posté sur la pull request (vide en cas d'échec). + pub markdown: String, + + /// Coût OpenRouter en USD, si connu. + pub cost: Option, + + /// Nombre de commentaires produits. + pub comments: u64, + + /// Durée du traitement en millisecondes. + pub duration_ms: u64, + + #[default(jiff::Timestamp::now())] + pub completed_at: Timestamp, +} diff --git a/crates/steep-server/src/state.rs b/crates/steep-server/src/state.rs index a6857d7..c66b4e1 100644 --- a/crates/steep-server/src/state.rs +++ b/crates/steep-server/src/state.rs @@ -1,11 +1,9 @@ -use apalis_redis::RedisStorage; - -use crate::{dedup::Dedup, env::EnvConfig, gitea::WebhookType}; +use crate::{dedup::Dedup, env::EnvConfig, job_queue::JobQueue}; #[derive(Clone)] pub struct AppState { - pub storage: RedisStorage, - pub bot_name: String, + pub queue: JobQueue, pub dedup: Dedup, + pub bot_name: String, pub config: EnvConfig, } diff --git a/crates/steep-server/toasty/history.toml b/crates/steep-server/toasty/history.toml new file mode 100644 index 0000000..c82f11c --- /dev/null +++ b/crates/steep-server/toasty/history.toml @@ -0,0 +1,6 @@ +version = 1 + +[[migrations]] +id = 3569579561409902287 +name = "0000_init.sql" +snapshot_name = "0000_snapshot.toml" diff --git a/crates/steep-server/toasty/migrations/0000_init.sql b/crates/steep-server/toasty/migrations/0000_init.sql new file mode 100644 index 0000000..5fccfab --- /dev/null +++ b/crates/steep-server/toasty/migrations/0000_init.sql @@ -0,0 +1,28 @@ +CREATE TYPE "job_status" AS ENUM ('pending', 'processing'); +CREATE TABLE "jobs" ( + "id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "event_id" BIGINT NOT NULL, + "repo" TEXT NOT NULL, + "pr" BIGINT NOT NULL, + "payload" JSONB NOT NULL, + "status" "job_status" NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL, + PRIMARY KEY ("id") +); +CREATE UNIQUE INDEX "index_jobs_by_event_id" ON "jobs" ("event_id"); +CREATE INDEX "index_jobs_by_status" ON "jobs" ("status"); +CREATE TABLE "reviews" ( + "id" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "event_id" BIGINT NOT NULL, + "repo" TEXT NOT NULL, + "pr" BIGINT NOT NULL, + "ok" BOOLEAN NOT NULL, + "model" TEXT NOT NULL, + "markdown" TEXT NOT NULL, + "cost" DOUBLE PRECISION, + "comments" BIGINT NOT NULL, + "duration_ms" BIGINT NOT NULL, + "completed_at" TIMESTAMPTZ(6) NOT NULL, + PRIMARY KEY ("id") +); +CREATE UNIQUE INDEX "index_reviews_by_event_id" ON "reviews" ("event_id"); diff --git a/crates/steep-server/toasty/snapshots/0000_snapshot.toml b/crates/steep-server/toasty/snapshots/0000_snapshot.toml new file mode 100644 index 0000000..1a0732c --- /dev/null +++ b/crates/steep-server/toasty/snapshots/0000_snapshot.toml @@ -0,0 +1,160 @@ +version = 1 + +[schema] + +[[schema.tables]] +id = 0 +name = "jobs" +primary_key = { columns = [{ table = 0, index = 0 }], index = { table = 0, index = 0 } } + +[[schema.tables.columns]] +id = { table = 0, index = 0 } +name = "id" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } +auto_increment = true + +[[schema.tables.columns]] +id = { table = 0, index = 1 } +name = "event_id" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 0, index = 2 } +name = "repo" +ty = "String" +storage_ty = "Text" + +[[schema.tables.columns]] +id = { table = 0, index = 3 } +name = "pr" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 0, index = 4 } +name = "payload" +ty = "String" +storage_ty = "Jsonb" + +[[schema.tables.columns]] +id = { table = 0, index = 5 } +name = "status" +ty = "String" +storage_ty = { Enum = { name = "job_status", variants = [{ name = "pending" }, { name = "processing" }] } } + +[[schema.tables.columns]] +id = { table = 0, index = 6 } +name = "created_at" +ty = "Timestamp" +storage_ty = { Timestamp = 6 } + +[[schema.tables.indices]] +id = { table = 0, index = 0 } +name = "index_jobs_by_id" +on = 0 +columns = [{ column = { table = 0, index = 0 }, op = "Eq", scope = "Partition" }] +unique = true +primary_key = true + +[[schema.tables.indices]] +id = { table = 0, index = 1 } +name = "index_jobs_by_event_id" +on = 0 +columns = [{ column = { table = 0, index = 1 }, op = "Eq", scope = "Partition" }] +unique = true + +[[schema.tables.indices]] +id = { table = 0, index = 2 } +name = "index_jobs_by_status" +on = 0 +columns = [{ column = { table = 0, index = 5 }, op = "Eq", scope = "Partition" }] + +[[schema.tables]] +id = 1 +name = "reviews" +primary_key = { columns = [{ table = 1, index = 0 }], index = { table = 1, index = 0 } } + +[[schema.tables.columns]] +id = { table = 1, index = 0 } +name = "id" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } +auto_increment = true + +[[schema.tables.columns]] +id = { table = 1, index = 1 } +name = "event_id" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 1, index = 2 } +name = "repo" +ty = "String" +storage_ty = "Text" + +[[schema.tables.columns]] +id = { table = 1, index = 3 } +name = "pr" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 1, index = 4 } +name = "ok" +ty = "Bool" +storage_ty = "Boolean" + +[[schema.tables.columns]] +id = { table = 1, index = 5 } +name = "model" +ty = "String" +storage_ty = "Text" + +[[schema.tables.columns]] +id = { table = 1, index = 6 } +name = "markdown" +ty = "String" +storage_ty = "Text" + +[[schema.tables.columns]] +id = { table = 1, index = 7 } +name = "cost" +ty = "F64" +storage_ty = { Float = 8 } +nullable = true + +[[schema.tables.columns]] +id = { table = 1, index = 8 } +name = "comments" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 1, index = 9 } +name = "duration_ms" +ty = "U64" +storage_ty = { UnsignedInteger = 8 } + +[[schema.tables.columns]] +id = { table = 1, index = 10 } +name = "completed_at" +ty = "Timestamp" +storage_ty = { Timestamp = 6 } + +[[schema.tables.indices]] +id = { table = 1, index = 0 } +name = "index_reviews_by_id" +on = 1 +columns = [{ column = { table = 1, index = 0 }, op = "Eq", scope = "Partition" }] +unique = true +primary_key = true + +[[schema.tables.indices]] +id = { table = 1, index = 1 } +name = "index_reviews_by_event_id" +on = 1 +columns = [{ column = { table = 1, index = 1 }, op = "Eq", scope = "Partition" }] +unique = true