From 478a62a264603dca591853764156a914b5dee66a Mon Sep 17 00:00:00 2001 From: torben Date: Mon, 15 Sep 2025 17:51:51 +0800 Subject: [PATCH] feat: implement payload-level filtering with CEL expressions Implements #2058 - Add optional filter field to endpoints that evaluates CEL expressions against message payload for content-based routing. --- server/Cargo.lock | 1420 +++++++++-------- server/Cargo.toml | 1 + server/svix-server/Cargo.toml | 2 + .../20250910000000_endpoint_filter.down.sql | 5 + .../20250910000000_endpoint_filter.up.sql | 5 + server/svix-server/src/core/message_app.rs | 1130 ++++++++++++- server/svix-server/src/db/models/endpoint.rs | 2 + .../src/v1/endpoints/endpoint/crud.rs | 34 + .../src/v1/endpoints/endpoint/mod.rs | 22 + .../svix-server/src/v1/endpoints/message.rs | 6 +- server/svix-server/src/worker.rs | 4 +- 11 files changed, 2001 insertions(+), 630 deletions(-) create mode 100644 server/svix-server/migrations/20250910000000_endpoint_filter.down.sql create mode 100644 server/svix-server/migrations/20250910000000_endpoint_filter.up.sql diff --git a/server/Cargo.lock b/server/Cargo.lock index db35c2e6d..c6058a20a 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -40,16 +40,16 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom 0.3.3", "once_cell", "serde", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -72,8 +72,8 @@ dependencies = [ "axum-extra", "bytes", "cfg-if", - "http 1.2.0", - "indexmap 2.7.1", + "http 1.3.1", + "indexmap 2.11.1", "schemars", "serde", "serde_json", @@ -93,7 +93,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -110,9 +110,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "amq-protocol" -version = "7.2.2" +version = "7.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a41c091e49edfcc098b4f90d4d7706a8cf9158034e84ebfee7ff346092f67c" +checksum = "587d313f3a8b4a40f866cc84b6059fe83133bf172165ac3b583129dd211d8e1c" dependencies = [ "amq-protocol-tcp", "amq-protocol-types", @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "amq-protocol-tcp" -version = "7.2.2" +version = "7.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed7a4a662472f88823ed2fc81babb0b00562f2c54284e3e7bffc02b6df649bf" +checksum = "dc707ab9aa964a85d9fc25908a3fdc486d2e619406883b3105b48bf304a8d606" dependencies = [ "amq-protocol-uri", "tcp-stream", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "amq-protocol-types" -version = "7.2.2" +version = "7.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6484fdc918c1b6e2ae8eda2914d19a5873e1975f93ad8d33d6a24d1d98df05" +checksum = "bf99351d92a161c61ec6ecb213bc7057f5b837dd4e64ba6cb6491358efd770c4" dependencies = [ "cookie-factory", "nom", @@ -147,21 +147,15 @@ dependencies = [ [[package]] name = "amq-protocol-uri" -version = "7.2.2" +version = "7.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7f2da69e0e1182765bf33407cd8a843f20791b5af2b57a2645818c4776c56c" +checksum = "f89f8273826a676282208e5af38461a07fe939def57396af6ad5997fcf56577d" dependencies = [ "amq-protocol-types", "percent-encoding", "url", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -173,9 +167,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -188,44 +182,60 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "antlr4rust" +version = "0.3.0-beta3" +source = "git+https://github.com/antlr4rust/antlr4.git?branch=rust-target#db442ee7bb7f47ed85356c2135bdfa2a4a686585" +dependencies = [ + "better_any", + "bit-set", + "byteorder", + "lazy_static", + "murmur3", "once_cell", - "windows-sys 0.59.0", + "parking_lot", + "typed-arena", + "uuid", ] [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arc-swap" @@ -241,9 +251,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "asn1-rs" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607495ec7113b178fbba7a6166a27f99e774359ef4823adbefd756b5b81d7970" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -251,7 +261,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", ] @@ -263,7 +273,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", "synstructure", ] @@ -275,7 +285,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -286,9 +296,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -298,14 +308,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ "async-task", "concurrent-queue", "fastrand 2.3.0", - "futures-lite 2.6.0", + "futures-lite 2.6.1", + "pin-project-lite", "slab", ] @@ -317,10 +328,10 @@ checksum = "13f937e26114b93193065fd44f507aa2e9169ad0cdabbb996920b1fe1ddea7ba" dependencies = [ "async-channel", "async-executor", - "async-io 2.4.0", - "async-lock 3.4.0", + "async-io 2.5.0", + "async-lock 3.4.1", "blocking", - "futures-lite 2.6.0", + "futures-lite 2.6.1", ] [[package]] @@ -356,21 +367,20 @@ dependencies = [ [[package]] name = "async-io" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" dependencies = [ - "async-lock 3.4.0", + "async-lock 3.4.1", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "parking", - "polling 3.7.4", - "rustix 0.38.44", + "polling 3.10.0", + "rustix 1.1.1", "slab", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -384,11 +394,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -424,7 +434,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -435,13 +445,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.87" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -455,9 +465,9 @@ dependencies = [ [[package]] name = "atomic" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ "bytemuck", ] @@ -470,9 +480,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" @@ -484,7 +494,7 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -517,7 +527,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "mime", @@ -541,7 +551,7 @@ dependencies = [ "fastrand 2.3.0", "futures-util", "headers", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "mime", @@ -562,7 +572,7 @@ dependencies = [ "arc-swap", "bytes", "fs-err", - "http 1.2.0", + "http 1.3.1", "http-body", "hyper", "hyper-util", @@ -584,9 +594,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -623,9 +633,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bb8" @@ -648,11 +658,17 @@ dependencies = [ "redis", ] +[[package]] +name = "better_any" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1795ebc740ea791ffbe6685e0688ab1effec16c2864e0476db40bfdf0c02cb3d" + [[package]] name = "bigdecimal" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" +checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" dependencies = [ "autocfg", "libm", @@ -664,9 +680,9 @@ dependencies = [ [[package]] name = "binstring" -version = "0.1.2" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed79c2a8151273c70956b5e3cdfdc1ff6c1a8b9779ba59c6807d281b32ee2f86" +checksum = "0669d5a35b64fdb5ab7fb19cae13148b6b5cbdf4b8247faf54ece47f699c8cef" [[package]] name = "bit-set" @@ -691,9 +707,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" dependencies = [ "serde", ] @@ -727,14 +743,14 @@ dependencies = [ [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ "async-channel", "async-task", "futures-io", - "futures-lite 2.6.0", + "futures-lite 2.6.1", "piper", ] @@ -746,21 +762,21 @@ checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecount" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" [[package]] name = "byteorder" @@ -791,18 +807,35 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" dependencies = [ + "find-msvc-tools", "shlex", ] +[[package]] +name = "cel" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ed6997671c8e5efbfe01fd91ac8e30c9bb433578250c14ca5735d4d75e68224" +dependencies = [ + "antlr4rust", + "chrono", + "lazy_static", + "nom", + "paste", + "regex", + "serde", + "thiserror 1.0.69", +] + [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -836,17 +869,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.2.0", ] [[package]] @@ -862,9 +894,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", "clap_derive", @@ -872,9 +904,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstream", "anstyle", @@ -884,21 +916,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cms" @@ -907,7 +939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" dependencies = [ "const-oid", - "der 0.7.9", + "der 0.7.10", "spki 0.7.3", "x509-cert", ] @@ -925,9 +957,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" @@ -991,9 +1023,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1074,9 +1106,9 @@ dependencies = [ [[package]] name = "ct-codecs" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b916ba8ce9e4182696896f015e8a5ae6081b305f74690baa8465e35f5a142ea4" +checksum = "9b10589d1a5e400d61f9f38f12f884cfd080ff345de8f17efda36fe0e4a02aa8" [[package]] name = "ctor" @@ -1085,14 +1117,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -1100,34 +1132,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "data-encoding" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "debugid" @@ -1152,9 +1184,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "der_derive", @@ -1185,14 +1217,14 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", "serde", @@ -1227,7 +1259,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -1244,9 +1276,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ecdsa" @@ -1254,7 +1286,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.9", + "der 0.7.10", "digest", "elliptic-curve", "rfc6979", @@ -1269,7 +1301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" dependencies = [ "ct-codecs", - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -1329,7 +1361,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -1341,7 +1373,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -1352,12 +1384,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.0", ] [[package]] @@ -1379,9 +1411,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -1390,11 +1422,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.4.0", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1435,9 +1467,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", @@ -1459,6 +1491,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "findshlibs" version = "0.10.2" @@ -1473,9 +1511,9 @@ dependencies = [ [[package]] name = "flagset" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "fluent-uri" @@ -1507,9 +1545,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -1528,9 +1566,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1631,9 +1669,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "fastrand 2.3.0", "futures-core", @@ -1650,7 +1688,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -1685,16 +1723,16 @@ dependencies = [ [[package]] name = "generator" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" dependencies = [ "cc", "cfg-if", "libc", "log", "rustversion", - "windows 0.61.3", + "windows", ] [[package]] @@ -1710,29 +1748,29 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.13.3+wasi-0.2.2", + "r-efi", + "wasi 0.14.4+wasi-0.2.4", "wasm-bindgen", - "windows-targets 0.52.6", ] [[package]] @@ -1743,9 +1781,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "group" @@ -1769,8 +1807,8 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.2.0", - "indexmap 2.7.1", + "http 1.3.1", + "indexmap 2.11.1", "slab", "tokio", "tokio-util", @@ -1785,9 +1823,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -1800,7 +1838,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -1812,7 +1850,7 @@ dependencies = [ "base64 0.22.1", "bytes", "headers-core", - "http 1.2.0", + "http 1.3.1", "httpdate", "mime", "sha1", @@ -1824,7 +1862,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.2.0", + "http 1.3.1", ] [[package]] @@ -1847,9 +1885,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1873,9 +1911,9 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.0", + "rand 0.9.2", "ring", - "thiserror 2.0.12", + "thiserror 2.0.16", "tinyvec", "tokio", "tracing", @@ -1895,10 +1933,10 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.0", + "rand 0.9.2", "resolv-conf", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tracing", ] @@ -1929,18 +1967,18 @@ checksum = "18492c9f6f9a560e0d346369b665ad2bdbc89fa9bceca75796584e79042694c3" [[package]] name = "hmac-sha256" -version = "1.1.8" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8575493d277c9092b988c780c94737fb9fd8651a1001e16bee3eccfc1baedb" +checksum = "ad6880c8d4a9ebf39c6e8b77007ce223f646a4d21ce29d99f70cb16420545425" dependencies = [ "digest", ] [[package]] name = "hmac-sha512" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b3a0f572aa8389d325f5852b9e0a333a15b0f86ecccbb3fdb6e97cd86dc67c" +checksum = "e89e8d20b3799fa526152a5301a771eaaad80857f83e01b23216ceaafb2d9280" dependencies = [ "digest", ] @@ -1956,24 +1994,13 @@ dependencies = [ [[package]] name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - -[[package]] -name = "hostname" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" dependencies = [ "cfg-if", "libc", - "windows 0.52.0", + "windows-link 0.1.3", ] [[package]] @@ -1989,9 +2016,9 @@ dependencies = [ [[package]] name = "http" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -2005,18 +2032,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.2.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.2.0", + "futures-core", + "http 1.3.1", "http-body", "pin-project-lite", ] @@ -2043,7 +2070,7 @@ dependencies = [ "futures-channel", "futures-core", "h2", - "http 1.2.0", + "http 1.3.1", "http-body", "httparse", "httpdate", @@ -2061,7 +2088,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527d4d619ca2c2aafa31ec139a3d1d60bf557bf7578a1f20f743637eccd9ca19" dependencies = [ - "http 1.2.0", + "http 1.3.1", "hyper", "hyper-util", "linked_hash_set", @@ -2081,7 +2108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.2.0", + "http 1.3.1", "hyper", "hyper-util", "log", @@ -2099,10 +2126,10 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.2.0", + "http 1.3.1", "hyper", "hyper-util", - "rustls 0.23.23", + "rustls 0.23.31", "rustls-pki-types", "tokio", "tokio-rustls 0.26.2", @@ -2112,9 +2139,9 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ "hyper", "hyper-util", @@ -2150,7 +2177,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "hyper", "ipnet", @@ -2165,16 +2192,17 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -2194,9 +2222,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2216,18 +2244,18 @@ dependencies = [ [[package]] name = "idna_mapping" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5422cc5bc64289a77dbb45e970b86b5e9a04cb500abc7240505aedc1bf40f38" +checksum = "11c13906586a4b339310541a274dd927aff6fcbb5b8e3af90634c4b31681c792" dependencies = [ "unicode-joining-type", ] [[package]] name = "if_chain" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" [[package]] name = "indexmap" @@ -2242,12 +2270,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "serde", ] @@ -2259,7 +2287,7 @@ checksum = "6c38228f24186d9cc68c729accb4d413be9eaed6ad07ff79e0270d9e56f3de13" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -2298,13 +2326,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + [[package]] name = "ipconfig" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.8", + "socket2 0.5.10", "widestring", "windows-sys 0.48.0", "winreg", @@ -2352,9 +2391,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" dependencies = [ "once_cell", "wasm-bindgen", @@ -2438,9 +2477,9 @@ dependencies = [ [[package]] name = "lapin" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b09a06f4bd4952a0fd0594f90d53cf4496b062f59acc838a2823e1bb7d95c" +checksum = "262f8d3c073435073c3e50bf2d63b361c143dcf418505b8c451fd23c7082a302" dependencies = [ "amq-protocol", "async-global-executor-trait", @@ -2475,9 +2514,20 @@ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags 2.9.4", + "libc", + "redox_syscall", +] [[package]] name = "libsqlite3-sys" @@ -2512,15 +2562,21 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.15" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -2528,9 +2584,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "loom" @@ -2551,12 +2607,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matchers" version = "0.2.0" @@ -2584,9 +2634,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "mime" @@ -2602,22 +2652,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] @@ -2648,7 +2698,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.2.0", + "http 1.3.1", "httparse", "memchr", "mime", @@ -2656,6 +2706,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "murmur3" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a198f9589efc03f544388dfc4a19fe8af4323662b62f598b8dcfdac62c14771c" +dependencies = [ + "byteorder", +] + [[package]] name = "native-tls" version = "0.2.14" @@ -2797,23 +2856,24 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -2849,7 +2909,7 @@ dependencies = [ "serde_json", "svix-ksuid 0.8.0", "sync_wrapper", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", "tokio", "tracing", @@ -2857,14 +2917,20 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" dependencies = [ "critical-section", "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2873,11 +2939,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.72" +version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", "cfg-if", "foreign-types", "libc", @@ -2894,7 +2960,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -2905,9 +2971,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.107" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", @@ -2937,7 +3003,7 @@ checksum = "6351496aeaa49d7c267fb480678d85d1cd30c5edb20b497c48c56f62a8c14b99" dependencies = [ "async-trait", "bytes", - "http 1.2.0", + "http 1.3.1", "opentelemetry", ] @@ -2949,7 +3015,7 @@ checksum = "29e1f9c8b032d4f635c730c0efcf731d5e2530ea13fa8bef7939ddc8420696bd" dependencies = [ "async-trait", "futures-core", - "http 1.2.0", + "http 1.3.1", "opentelemetry", "opentelemetry-proto", "opentelemetry_sdk", @@ -3000,20 +3066,21 @@ dependencies = [ [[package]] name = "ordered-float" -version = "3.9.2" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ "num-traits", ] [[package]] name = "os_info" -version = "3.10.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" +checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" dependencies = [ "log", + "plist", "serde", "windows-sys 0.52.0", ] @@ -3039,7 +3106,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -3050,23 +3117,23 @@ checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" [[package]] name = "p12-keystore" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a09eaa3a6d8884c204c2ab17e313f563b524362e62567f09ba27857a6e31257f" +checksum = "3cae83056e7cb770211494a0ecf66d9fa7eba7d00977e5bb91f0e925b40b937f" dependencies = [ "cbc", "cms", - "der 0.7.9", + "der 0.7.10", "des", "hex", "hmac", "pkcs12", "pkcs5", - "rand 0.9.0", + "rand 0.9.2", "rc2", "sha1", "sha2", - "thiserror 2.0.12", + "thiserror 2.0.16", "x509-parser", ] @@ -3102,9 +3169,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -3112,9 +3179,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -3123,6 +3190,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pbkdf2" version = "0.12.2" @@ -3153,7 +3226,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -3176,15 +3249,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pgvector" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e8871b6d7ca78348c6cd29b911b94851f3429f0cd403130ca17f26c1fb91a6" +checksum = "fc58e2d255979a31caa7cabfa7aac654af0354220719ab7a68520ae7a91e8c0b" dependencies = [ "serde", ] @@ -3206,7 +3279,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -3223,9 +3296,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pinky-swear" -version = "6.2.0" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cfae3ead413ca051a681152bd266438d3bfa301c9bdf836939a14c721bb2a21" +checksum = "b1ea6e230dd3a64d61bcb8b79e597d3ab6b4c94ec7a234ce687dd718b4f2e657" dependencies = [ "doc-comment", "flume", @@ -3262,7 +3335,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.9", + "der 0.7.10", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -3275,7 +3348,7 @@ checksum = "695b3df3d3cc1015f12d70235e35b6b79befc5fa7a9b95b951eab1dd07c9efc2" dependencies = [ "cms", "const-oid", - "der 0.7.9", + "der 0.7.10", "digest", "spki 0.7.3", "x509-cert", @@ -3290,7 +3363,7 @@ checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" dependencies = [ "aes", "cbc", - "der 0.7.9", + "der 0.7.10", "pbkdf2", "scrypt", "sha2", @@ -3313,7 +3386,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.9", + "der 0.7.10", "spki 0.7.3", ] @@ -3323,6 +3396,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plist" +version = "1.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" +dependencies = [ + "base64 0.22.1", + "indexmap 2.11.1", + "quick-xml", + "serde", + "time", +] + [[package]] name = "polling" version = "2.8.0" @@ -3341,17 +3427,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.4" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "pin-project-lite", - "rustix 0.38.44", - "tracing", - "windows-sys 0.59.0", + "rustix 1.1.1", + "windows-sys 0.60.2", ] [[package]] @@ -3379,11 +3464,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -3447,14 +3532,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -3467,7 +3552,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", "version_check", "yansi", ] @@ -3492,20 +3577,23 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "quick-xml" +version = "0.38.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +dependencies = [ + "memchr", +] [[package]] name = "quinn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", @@ -3513,9 +3601,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.23", - "socket2 0.5.8", - "thiserror 2.0.12", + "rustls 0.23.31", + "socket2 0.6.0", + "thiserror 2.0.16", "tokio", "tracing", "web-time", @@ -3523,20 +3611,20 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.1", + "getrandom 0.3.3", "lru-slab", - "rand 0.9.0", + "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.23", + "rustls 0.23.31", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.16", "tinyvec", "tracing", "web-time", @@ -3544,27 +3632,33 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.8", + "socket2 0.6.0", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -3578,13 +3672,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -3613,7 +3706,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -3622,7 +3715,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", ] [[package]] @@ -3666,7 +3759,7 @@ dependencies = [ "num-bigint", "percent-encoding", "pin-project-lite", - "rand 0.9.0", + "rand 0.9.2", "ryu", "sha1_smol", "socket2 0.6.0", @@ -3678,11 +3771,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", ] [[package]] @@ -3702,7 +3795,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -3721,9 +3814,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -3733,9 +3826,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -3744,9 +3837,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "reqwest" @@ -3760,7 +3853,7 @@ dependencies = [ "futures-core", "futures-util", "hickory-resolver", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -3774,7 +3867,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.23", + "rustls 0.23.31", "rustls-pki-types", "serde", "serde_json", @@ -3795,13 +3888,9 @@ dependencies = [ [[package]] name = "resolv-conf" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname 0.3.1", - "quick-error", -] +checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" [[package]] name = "rfc6979" @@ -3815,13 +3904,13 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -3850,9 +3939,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", @@ -3870,9 +3959,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.36.0" +version = "1.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" +checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d" dependencies = [ "arrayvec", "num-traits", @@ -3881,9 +3970,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -3925,15 +4014,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "9621e389a110cae094269936383d69b869492f03e5c1ed2d575a53c029d4441d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", "errno", "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "linux-raw-sys 0.11.0", + "linux-raw-sys 0.9.4", + "windows-sys 0.61.0", ] [[package]] @@ -3945,36 +4035,36 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.23" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.4", "subtle", "zeroize", ] [[package]] name = "rustls-connector" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a980454b497c439c274f2feae2523ed8138bbd3d323684e1435fec62f800481" +checksum = "70cc376c6ba1823ae229bacf8ad93c136d93524eab0e4e5e0e4f96b9c4e5b212" dependencies = [ "log", - "rustls 0.23.23", + "rustls 0.23.31", "rustls-native-certs", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.4", ] [[package]] @@ -4001,11 +4091,12 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time", + "zeroize", ] [[package]] @@ -4019,11 +4110,22 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.103.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -4042,11 +4144,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.0", ] [[package]] @@ -4058,7 +4160,7 @@ dependencies = [ "chrono", "dyn-clone", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.11.1", "schemars_derive", "serde", "serde_json", @@ -4074,7 +4176,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -4110,14 +4212,14 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "sea-orm" -version = "1.1.7" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3417812d38049e8ec3d588c03570f8c60de811d2453fb48e424045a1600ffd86" +checksum = "458d38dfa73e8ab64260f9fd96d61e1ca96a312d06e94b71615a417ef29efcac" dependencies = [ "async-stream", "async-trait", @@ -4135,7 +4237,7 @@ dependencies = [ "serde_json", "sqlx", "strum", - "thiserror 1.0.69", + "thiserror 2.0.16", "time", "tracing", "url", @@ -4144,23 +4246,23 @@ dependencies = [ [[package]] name = "sea-orm-macros" -version = "1.1.7" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d705ba84e1c74c8ac27784e4ac6f21584058c1dc0cadb9d39b43e109fcf8139c" +checksum = "af976292446b09dd51d7b1784d6195dec76844e9e9e980b5fb12634ef417d6ea" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "sea-bae", - "syn 2.0.99", + "syn 2.0.106", "unicode-ident", ] [[package]] name = "sea-query" -version = "0.32.2" +version = "0.32.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b731192738ebf56d20580fc8ba2d23940333befe900b04dd08a26a77cd056f02" +checksum = "8a5d1c518eaf5eda38e5773f902b26ab6d5e9e9e2bb2349ca6c64cf96f80448c" dependencies = [ "chrono", "inherent", @@ -4187,7 +4289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der 0.7.9", + "der 0.7.10", "generic-array", "pkcs8 0.10.2", "subtle", @@ -4200,7 +4302,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", "core-foundation", "core-foundation-sys", "libc", @@ -4209,9 +4311,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -4260,7 +4362,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" dependencies = [ - "hostname 0.4.0", + "hostname", "libc", "os_info", "rustc_version", @@ -4333,22 +4435,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -4359,14 +4461,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -4405,14 +4507,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -4448,9 +4550,9 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -4474,9 +4576,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -4503,18 +4605,15 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] @@ -4531,9 +4630,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4575,14 +4674,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.9", + "der 0.7.10", ] [[package]] name = "sqlx" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", @@ -4593,59 +4692,59 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ + "base64 0.22.1", "bytes", "chrono", "crc", "crossbeam-queue", "either", - "event-listener 5.4.0", + "event-listener 5.4.1", "futures-core", "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "hashlink", - "indexmap 2.7.1", + "indexmap 2.11.1", "log", "memchr", "once_cell", "percent-encoding", - "rustls 0.23.23", - "rustls-pemfile", + "rustls 0.23.31", "serde", "serde_json", "sha2", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tokio-stream", "tracing", "url", - "webpki-roots 0.26.8", + "webpki-roots 0.26.11", ] [[package]] name = "sqlx-macros" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "sqlx-macros-core" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" dependencies = [ "dotenvy", "either", @@ -4661,21 +4760,20 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.99", - "tempfile", + "syn 2.0.106", "tokio", "url", ] [[package]] name = "sqlx-mysql" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.9.0", + "bitflags 2.9.4", "byteorder", "bytes", "chrono", @@ -4698,27 +4796,27 @@ dependencies = [ "once_cell", "percent-encoding", "rand 0.8.5", - "rsa 0.9.7", + "rsa 0.9.8", "serde", "sha1", "sha2", "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.16", "tracing", "whoami", ] [[package]] name = "sqlx-postgres" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.9.0", + "bitflags 2.9.4", "byteorder", "chrono", "crc", @@ -4743,16 +4841,16 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.16", "tracing", "whoami", ] [[package]] name = "sqlx-sqlite" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", "chrono", @@ -4768,6 +4866,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", + "thiserror 2.0.16", "tracing", "url", ] @@ -4809,28 +4908,32 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svix" -version = "1.61.3" +version = "1.76.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39858167f8dbac055ccd736d1014b9c1c7ef549f29eb57d2705ef67893520ffd" +checksum = "dd1380c2d8e3af9875338f5b0bf38553f48ad2f2d295de9c6ad77c81499367c0" dependencies = [ "base64 0.13.1", "hmac-sha256", "http 0.2.12", - "http 1.2.0", + "http 1.3.1", "http-body-util", "hyper", "hyper-rustls 0.26.0", "hyper-util", "itertools", "js_option", - "rand 0.9.0", + "percent-encoding", + "rand 0.9.2", "serde", "serde_json", "serde_repr", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", "tokio", + "tower-service", + "tracing", "url", + "uuid", ] [[package]] @@ -4842,7 +4945,7 @@ dependencies = [ "base-encode", "byteorder", "chrono", - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -4853,7 +4956,7 @@ checksum = "66f014385b7fc154f59e9480770c2187b6e61037c2439895788a9a4d421d7859" dependencies = [ "base-encode", "byteorder", - "getrandom 0.2.15", + "getrandom 0.2.16", "time", ] @@ -4872,6 +4975,7 @@ dependencies = [ "bb8-redis", "blake2", "bytes", + "cel", "chacha20poly1305", "chrono", "clap", @@ -4886,13 +4990,13 @@ dependencies = [ "hickory-resolver", "hmac-sha256", "http 0.2.12", - "http 1.2.0", + "http 1.3.1", "http-body-util", "hyper", "hyper-openssl", "hyper-util", "idna_adapter", - "indexmap 2.7.1", + "indexmap 2.11.1", "ipnet", "itertools", "jsonschema", @@ -4900,6 +5004,7 @@ dependencies = [ "lapin", "num_enum", "omniqueue", + "once_cell", "openssl", "opentelemetry", "opentelemetry-http", @@ -4920,7 +5025,7 @@ dependencies = [ "svix", "svix-ksuid 0.5.3", "svix-server_derive", - "thiserror 2.0.12", + "thiserror 2.0.16", "tikv-jemallocator", "time", "tokio", @@ -4941,7 +5046,7 @@ version = "1.76.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -4957,9 +5062,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -4977,13 +5082,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -5006,16 +5111,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.17.1" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ - "cfg-if", "fastrand 2.3.0", - "getrandom 0.3.1", + "getrandom 0.3.3", "once_cell", - "rustix 0.38.44", - "windows-sys 0.59.0", + "rustix 1.1.1", + "windows-sys 0.60.2", ] [[package]] @@ -5029,11 +5133,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.16", ] [[package]] @@ -5044,28 +5148,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -5090,12 +5193,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde", @@ -5105,15 +5207,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -5121,9 +5223,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -5136,20 +5238,22 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.8", + "slab", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5160,7 +5264,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -5201,7 +5305,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.23", + "rustls 0.23.31", "tokio", ] @@ -5231,9 +5335,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -5243,26 +5347,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.11.1", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tonic" version = "0.12.3" @@ -5275,7 +5386,7 @@ dependencies = [ "base64 0.22.1", "bytes", "h2", - "http 1.2.0", + "http 1.3.1", "http-body", "http-body-util", "hyper", @@ -5284,7 +5395,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "socket2 0.5.8", + "socket2 0.5.10", "tokio", "tokio-stream", "tower 0.4.13", @@ -5335,10 +5446,10 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", "bytes", "futures-util", - "http 1.2.0", + "http 1.3.1", "http-body", "iri-string", "pin-project-lite", @@ -5375,20 +5486,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -5460,6 +5571,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.18.0" @@ -5498,9 +5615,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-joining-type" -version = "0.7.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f8cb47ccb8bc750808755af3071da4a10dcd147b68fc874b7ae4b12543f6f5" +checksum = "d8d00a78170970967fdb83f9d49b92f959ab2bb829186b113e4f4604ad98e180" [[package]] name = "unicode-normalization" @@ -5548,9 +5665,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -5578,12 +5695,14 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.15.1" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -5678,17 +5797,17 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.4+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -5703,40 +5822,41 @@ version = "0.12.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" dependencies = [ - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" dependencies = [ "cfg-if", "js-sys", @@ -5747,9 +5867,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5757,31 +5877,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" dependencies = [ "js-sys", "wasm-bindgen", @@ -5799,11 +5919,11 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.8" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "rustls-pki-types", + "webpki-roots 1.0.2", ] [[package]] @@ -5817,19 +5937,19 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall", + "libredox", "wasite", ] [[package]] name = "widestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" [[package]] name = "winapi" @@ -5853,16 +5973,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.61.3" @@ -5870,9 +5980,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core 0.61.2", + "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -5882,16 +5992,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", + "windows-core", ] [[package]] @@ -5902,7 +6003,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -5913,8 +6014,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core 0.61.2", - "windows-link", + "windows-core", + "windows-link 0.1.3", "windows-threading", ] @@ -5926,7 +6027,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -5937,7 +6038,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] @@ -5946,14 +6047,20 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-numerics" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core 0.61.2", - "windows-link", + "windows-core", + "windows-link 0.1.3", ] [[package]] @@ -5962,7 +6069,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5971,7 +6078,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -6001,6 +6108,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -6025,20 +6150,37 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link 0.1.3", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows-threading" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -6053,6 +6195,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -6065,6 +6213,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -6077,12 +6231,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -6095,6 +6261,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -6107,6 +6279,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -6119,6 +6297,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -6131,11 +6315,17 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -6151,13 +6341,10 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.33.0" +name = "wit-bindgen" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags 2.9.0", -] +checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" [[package]] name = "x509-cert" @@ -6166,7 +6353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" dependencies = [ "const-oid", - "der 0.7.9", + "der 0.7.10", "spki 0.7.3", ] @@ -6183,7 +6370,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 2.0.12", + "thiserror 2.0.16", "time", ] @@ -6195,43 +6382,22 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.99", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.106", ] [[package]] diff --git a/server/Cargo.toml b/server/Cargo.toml index 27de94eaa..0689e6cc0 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -34,3 +34,4 @@ svix-server_derive = { opt-level = 0 } [patch.crates-io] hyper = { git = "https://github.com/svix/hyper.git", rev = "18c04c321e1a9a4958ad14b880f7403acbe1c914" } +antlr4rust = { git = "https://github.com/antlr4rust/antlr4.git", branch = "rust-target" } diff --git a/server/svix-server/Cargo.toml b/server/svix-server/Cargo.toml index f0d83f8c8..282fb3f93 100644 --- a/server/svix-server/Cargo.toml +++ b/server/svix-server/Cargo.toml @@ -92,6 +92,8 @@ urlencoding = "2.1.2" # haven't gotten around to doing a proper upgrade yet (0.17 is a large # rewrite with a barely-useful changelog) validator = { git = "https://github.com/svix/validator.git", rev = "aebdc34a4ed72524902ff6d63397b9c435b0578f", features = ["derive"] } +cel = "0.11.1" +once_cell = "1.19" [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = { version = "0.6", optional = true } diff --git a/server/svix-server/migrations/20250910000000_endpoint_filter.down.sql b/server/svix-server/migrations/20250910000000_endpoint_filter.down.sql new file mode 100644 index 000000000..b5082acf7 --- /dev/null +++ b/server/svix-server/migrations/20250910000000_endpoint_filter.down.sql @@ -0,0 +1,5 @@ +-- Drop filter column from endpoint table +ALTER TABLE endpoint + DROP COLUMN IF EXISTS filter; + + diff --git a/server/svix-server/migrations/20250910000000_endpoint_filter.up.sql b/server/svix-server/migrations/20250910000000_endpoint_filter.up.sql new file mode 100644 index 000000000..8e08a66b4 --- /dev/null +++ b/server/svix-server/migrations/20250910000000_endpoint_filter.up.sql @@ -0,0 +1,5 @@ +-- Add optional filter column to endpoint table for payload-level filtering expressions +ALTER TABLE endpoint + ADD COLUMN IF NOT EXISTS filter TEXT NULL; + + diff --git a/server/svix-server/src/core/message_app.rs b/server/svix-server/src/core/message_app.rs index 79b572544..f5d19856c 100644 --- a/server/svix-server/src/core/message_app.rs +++ b/server/svix-server/src/core/message_app.rs @@ -3,8 +3,92 @@ use std::{collections::HashSet, time::Duration}; use chrono::{DateTime, FixedOffset, Utc}; use sea_orm::{DatabaseConnection, DatabaseTransaction, TransactionTrait}; use serde::{Deserialize, Serialize}; +use serde_json::Value as JsonValue; +use cel::{Value, Context, Program, objects::{Map, Key}}; +use std::sync::Arc; + +#[cfg(debug_assertions)] +use std::time::Instant; +#[cfg(debug_assertions)] +use tracing::{debug, warn}; use super::types::EventTypeName; + +/// Maximum length for CEL expressions to prevent abuse +const MAX_CEL_EXPRESSION_LENGTH: usize = 2048; + +/// Maximum complexity for CEL expressions (approximate token count) +const MAX_CEL_COMPLEXITY: usize = 50; + +/// Warning threshold for CEL expression execution time (milliseconds) +#[cfg(debug_assertions)] +const CEL_EXECUTION_WARNING_THRESHOLD_MS: u128 = 10; + +/// Error threshold for CEL expression execution time (milliseconds) +#[cfg(debug_assertions)] +const CEL_EXECUTION_ERROR_THRESHOLD_MS: u128 = 100; + + +/// CEL expression execution performance metrics +/// Only available when debug mode is enabled +#[cfg(debug_assertions)] +#[derive(Debug, Clone)] +pub struct CelExecutionMetrics { + pub expression: String, + pub execution_time_ms: u128, + pub complexity: usize, + pub success: bool, + pub error_message: Option, +} + +#[cfg(debug_assertions)] +impl CelExecutionMetrics { + pub fn new(expression: String, execution_time_ms: u128, complexity: usize, success: bool, error_message: Option) -> Self { + Self { + expression, + execution_time_ms, + complexity, + success, + error_message, + } + } + + /// Log performance metrics with appropriate level based on execution time + pub fn log_performance(&self) { + if self.execution_time_ms >= CEL_EXECUTION_ERROR_THRESHOLD_MS { + warn!( + "CEL expression execution exceeded error threshold: {}ms (threshold: {}ms) - expression: '{}', complexity: {}, success: {}", + self.execution_time_ms, + CEL_EXECUTION_ERROR_THRESHOLD_MS, + self.expression, + self.complexity, + self.success + ); + } else if self.execution_time_ms >= CEL_EXECUTION_WARNING_THRESHOLD_MS { + warn!( + "CEL expression execution exceeded warning threshold: {}ms (threshold: {}ms) - expression: '{}', complexity: {}, success: {}", + self.execution_time_ms, + CEL_EXECUTION_WARNING_THRESHOLD_MS, + self.expression, + self.complexity, + self.success + ); + } else { + debug!( + "CEL expression executed: {}ms - expression: '{}', complexity: {}, success: {}", + self.execution_time_ms, + self.expression, + self.complexity, + self.success + ); + } + + if let Some(ref error) = self.error_message { + warn!("CEL expression execution failed: {}", error); + } + } +} + use crate::{ core::{ cache::{kv_def, Cache, CacheBehavior, CacheKey, CacheValue}, @@ -18,6 +102,138 @@ use crate::{ error::{Error, Result}, }; +/// Convert JSON value to CEL value +fn json_to_cel_value(json: &JsonValue) -> Result { + match json { + JsonValue::Null => Ok(Value::Null), + JsonValue::Bool(b) => Ok(Value::Bool(*b)), + JsonValue::Number(n) => { + if let Some(i) = n.as_i64() { + Ok(Value::Int(i)) + } else if let Some(u) = n.as_u64() { + Ok(Value::UInt(u)) + } else if let Some(f) = n.as_f64() { + Ok(Value::Float(f)) + } else { + Err("Invalid number format".to_string()) + } + } + JsonValue::String(s) => Ok(Value::String(Arc::new(s.clone()))), + JsonValue::Array(arr) => { + let mut cel_array = Vec::new(); + for item in arr { + cel_array.push(json_to_cel_value(item)?); + } + Ok(Value::List(Arc::new(cel_array))) + } + JsonValue::Object(obj) => { + let mut cel_map = std::collections::HashMap::new(); + for (k, v) in obj { + cel_map.insert(Key::String(Arc::new(k.clone())), json_to_cel_value(v)?); + } + Ok(Value::Map(Map { map: Arc::new(cel_map) })) + } + } +} + +/// Calculate the approximate complexity of a CEL expression +/// This is a simple heuristic based on counting operators, function calls, and field accesses +fn calculate_cel_complexity(expr: &str) -> usize { + let mut complexity = 0; + let chars: Vec = expr.chars().collect(); + let mut i = 0; + + while i < chars.len() { + match chars[i] { + // Logical operators + '&' if i + 1 < chars.len() && chars[i + 1] == '&' => { + complexity += 2; + i += 2; // Skip both characters + continue; + } + '|' if i + 1 < chars.len() && chars[i + 1] == '|' => { + complexity += 2; + i += 2; // Skip both characters + continue; + } + // Comparison operators + '=' if i + 1 < chars.len() && chars[i + 1] == '=' => { + complexity += 2; + i += 2; // Skip both characters + continue; + } + '!' if i + 1 < chars.len() && chars[i + 1] == '=' => { + complexity += 2; + i += 2; // Skip both characters + continue; + } + '<' | '>' => complexity += 1, + // Arithmetic operators + '+' | '-' | '*' | '/' | '%' => complexity += 1, + // Field access and function calls + '.' => complexity += 1, + '(' => complexity += 1, + '[' => complexity += 1, + // String literals (approximate) + '\'' | '"' => { + complexity += 1; + // Skip to end of string + let quote_char = chars[i]; + i += 1; + while i < chars.len() && chars[i] != quote_char { + if chars[i] == '\\' && i + 1 < chars.len() { + i += 1; // Skip escaped character + } + i += 1; + } + continue; + } + _ => {} + } + i += 1; + } + + complexity +} + +/// Validates a CEL expression by attempting to compile it +/// Returns Ok(()) if the expression is valid, Err(String) with error message if invalid +pub fn validate_cel_expression(expr: &str) -> Result<(), String> { + if expr.trim().is_empty() { + return Ok(()); + } + + // Check expression length limit + if expr.len() > MAX_CEL_EXPRESSION_LENGTH { + return Err(format!( + "CEL expression too long: {} characters (max: {})", + expr.len(), + MAX_CEL_EXPRESSION_LENGTH + )); + } + + // Check expression complexity limit + let complexity = calculate_cel_complexity(expr); + if complexity > MAX_CEL_COMPLEXITY { + return Err(format!( + "CEL expression too complex: {} complexity score (max: {})", + complexity, + MAX_CEL_COMPLEXITY + )); + } + + // Use panic-safe compilation for validation + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + Program::compile(expr) + })); + + match result { + Ok(Ok(_)) => Ok(()), + Ok(Err(_e)) => Err(format!("CEL compilation error")), + Err(_) => Err(format!("CEL compilation panic")), + } +} + /// The information cached during the creation of a message. Includes a [`Vec`] of all endpoints /// associated with the given application and organization ID. #[derive(Deserialize, Serialize, Debug, Clone)] @@ -112,6 +328,7 @@ impl CreateMessageApp { trigger_type: MessageAttemptTriggerType, event_type: &EventTypeName, channels: Option<&EventChannelSet>, + payload: Option<&JsonValue>, ) -> Vec { self.endpoints .iter() @@ -140,6 +357,150 @@ impl CreateMessageApp { .unwrap_or(true) )) }) + .filter(|endpoint| { + + tracing::debug!( + "endpoint.filter: {:?}, payload: {:?}", + endpoint.filter, + payload + ); + + match (&endpoint.filter, payload) { + (Some(expr), Some(payload_json)) => { + // Start performance monitoring (only in debug mode) + #[cfg(debug_assertions)] + let start_time = Instant::now(); + #[cfg(debug_assertions)] + let complexity = calculate_cel_complexity(expr); + #[cfg(debug_assertions)] + let mut success = false; + #[cfg(debug_assertions)] + let mut error_message = None; + + let payload_value = match json_to_cel_value(payload_json) { + Ok(v) => v, + Err(e) => { + tracing::debug!("JSON to CEL conversion error: {:?}", e); + return false; + } + }; + + tracing::debug!( + "payload_value: {:?}", + payload_value + ); + + let result = (|| -> bool { + let mut context = Context::default(); + + if let Some(payload_obj) = payload_json.as_object() { + for (key, value) in payload_obj { + match json_to_cel_value(value) { + Ok(cel_value) => { + if let Err(e) = context.add_variable(key, cel_value) { + #[cfg(debug_assertions)] + { + error_message = Some(format!("Failed to add variable '{}': {}", key, e)); + } + tracing::debug!("Failed to add variable '{}': {:?}", key, e); + return false; + } + } + Err(e) => { + #[cfg(debug_assertions)] + { + error_message = Some(format!("Failed to convert field '{}' to CEL value: {}", key, e)); + } + tracing::debug!("Failed to convert field '{}' to CEL value: {:?}", key, e); + return false; + } + } + } + } else { + #[cfg(debug_assertions)] + { + error_message = Some(format!("Payload is not a JSON object")); + } + tracing::debug!("Payload is not a JSON object"); + return false; + } + + let program = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + Program::compile(expr) + })) { + Ok(Ok(program)) => program, + Ok(Err(e)) => { + #[cfg(debug_assertions)] + { + error_message = Some(format!("Failed to compile CEL expression: {:?}", e)); + } + tracing::debug!("CEL compile error: {:?}", e); + return false; + } + Err(_) => { + #[cfg(debug_assertions)] + { + error_message = Some(format!("CEL compilation panic")); + } + tracing::debug!("CEL compilation panic"); + return false; + } + }; + + match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + program.execute(&context) + })) { + Ok(Ok(val)) => { + #[cfg(debug_assertions)] + { + success = true; + } + match val { + Value::Bool(b) => b, + _ => false, + } + } + Ok(Err(_e)) => { + #[cfg(debug_assertions)] + { + error_message = Some(format!("Failed to execute CEL expression: {}", _e)); + } + false + } + Err(_) => { + #[cfg(debug_assertions)] + { + error_message = Some(format!("CEL execution panic")); + } + tracing::debug!("CEL execution panic"); + false + } + } + })(); + + // Record performance metrics (only in debug mode) + #[cfg(debug_assertions)] + { + let execution_time = start_time.elapsed(); + let execution_time_ms = execution_time.as_millis(); + + let metrics = CelExecutionMetrics::new( + expr.clone(), + execution_time_ms, + complexity, + success, + error_message, + ); + + // Log performance metrics + metrics.log_performance(); + } + + result + } + _ => true, + } + }) .cloned() .collect() } @@ -153,6 +514,7 @@ pub struct CreateMessageEndpoint { pub key: EndpointSecretInternal, pub event_types_ids: Option, pub channels: Option, + pub filter: Option, pub rate_limit: Option, // Same type as the `DateTimeWithTimeZone from SeaORM used in the endpoint model pub first_failure_at: Option>, @@ -191,6 +553,7 @@ impl TryFrom for CreateMessageEndpoint { old_signing_keys: m.old_keys, event_types_ids: m.event_types_ids, channels: m.channels, + filter: m.filter, rate_limit: m .rate_limit .map(|v| v.try_into()) @@ -218,7 +581,7 @@ mod tests { use base64::{engine::general_purpose::STANDARD, Engine}; use chrono::Utc; - use super::CreateMessageEndpoint; + use super::{CreateMessageApp, CreateMessageEndpoint}; use crate::core::{ cryptography::Encryption, types::{ @@ -257,6 +620,7 @@ mod tests { old_signing_keys, event_types_ids: None, channels: None, + filter: None, rate_limit: None, first_failure_at: None, headers: None, @@ -268,4 +632,768 @@ mod tests { assert_eq!(keys.len(), 2); } + + #[test] + fn test_filtered_endpoints_with_cel_filter() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Create test endpoints + let endpoint_with_filter = CreateMessageEndpoint { + id: EndpointId::from("filtered_endpoint".to_string()), + url: "https://example.com/filtered".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("age >= 18".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let endpoint_without_filter = CreateMessageEndpoint { + id: EndpointId::from("unfiltered_endpoint".to_string()), + url: "https://example.com/unfiltered".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: None, + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints: vec![endpoint_with_filter, endpoint_without_filter], + deleted: false, + }; + + // Test with payload that should pass filter (age >= 18) + let adult_payload = json!({"name": "John", "age": 25}); + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&adult_payload), + ); + + // Expect both endpoints: one passes filter, one has no filter + assert_eq!(filtered_endpoints.len(), 2); + + // Test with payload that should fail filter (age < 18) + let minor_payload = json!({"name": "Jane", "age": 16}); + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&minor_payload), + ); + + // Expect only the unfiltered endpoint + assert_eq!(filtered_endpoints.len(), 1); + + // Test with no payload + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + None, + ); + + // Both endpoints should be included (no payload means no filtering) + assert_eq!(filtered_endpoints.len(), 2); + } + + #[test] + fn test_cel_filter_edge_cases() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Test with complex nested JSON payload + let complex_payload = json!({ + "user": { + "profile": { + "age": 25, + "name": "John", + "active": true, + "balance": 1000.50 + }, + "settings": { + "notifications": false, + "theme": "dark" + } + }, + "metadata": { + "source": "mobile", + "version": "1.0.0" + } + }); + + let endpoints = vec![ + // Test nested object access + CreateMessageEndpoint { + id: EndpointId::from("nested_filter".to_string()), + url: "https://example.com/nested".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("user.profile.age >= 18".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test string operations + CreateMessageEndpoint { + id: EndpointId::from("string_filter".to_string()), + url: "https://example.com/string".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("user.profile.name.startsWith('J')".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test boolean operations + CreateMessageEndpoint { + id: EndpointId::from("bool_filter".to_string()), + url: "https://example.com/bool".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("user.profile.active == true".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test complex expression with multiple conditions + CreateMessageEndpoint { + id: EndpointId::from("complex_filter".to_string()), + url: "https://example.com/complex".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("user.profile.age >= 18 && user.profile.balance >= 500.0 && user.profile.active == true".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + ]; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints, + deleted: false, + }; + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&complex_payload), + ); + + // All filters should pass for this complex payload + assert_eq!(filtered_endpoints.len(), 4); + } + + #[test] + fn test_cel_filter_error_handling() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + let endpoints = vec![ + // Test invalid CEL expression + CreateMessageEndpoint { + id: EndpointId::from("invalid_filter".to_string()), + url: "https://example.com/invalid".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("invalid syntax here".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test missing field access + CreateMessageEndpoint { + id: EndpointId::from("missing_field".to_string()), + url: "https://example.com/missing".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("nonexistent.field >= 18".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test type mismatch + CreateMessageEndpoint { + id: EndpointId::from("type_mismatch".to_string()), + url: "https://example.com/type".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("age >= 18".to_string()), // age is number, not string + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + ]; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints, + deleted: false, + }; + + let simple_payload = json!({"age": 25, "name": "John"}); + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&simple_payload), + ); + + // Only the endpoint without filter should pass (the one with invalid filter should be filtered out) + assert_eq!(filtered_endpoints.len(), 1); + } + + #[test] + fn test_cel_filter_array_access() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Test with array payload + let array_payload = json!({ + "users": [ + {"name": "John", "age": 25}, + {"name": "Jane", "age": 16}, + {"name": "Bob", "age": 30} + ], + "count": 3 + }); + + let endpoints = vec![ + // Test array element access + CreateMessageEndpoint { + id: EndpointId::from("array_filter".to_string()), + url: "https://example.com/array".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("users[0].age >= 18".to_string()), // First user's age + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + // Test array length check + CreateMessageEndpoint { + id: EndpointId::from("array_length".to_string()), + url: "https://example.com/length".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("count >= 2.0".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }, + ]; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints, + deleted: false, + }; + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&array_payload), + ); + + // Both filters should pass + assert_eq!(filtered_endpoints.len(), 2); + } + + #[test] + fn test_cel_filter_real_integration_web3_scenarios() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Create endpoints for Web3 scenarios + let defi_endpoint = CreateMessageEndpoint { + id: EndpointId::from("defi_endpoint".to_string()), + url: "https://defi.com/webhook".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("amount >= 1000.0 && token == 'USDC'".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let nft_endpoint = CreateMessageEndpoint { + id: EndpointId::from("nft_endpoint".to_string()), + url: "https://nft.com/webhook".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("price >= 1.0 && collection == 'BoredApe'".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints: vec![defi_endpoint, nft_endpoint], + deleted: false, + }; + + // Test DeFi transaction that should pass + let defi_payload = json!({ + "amount": 1500.0, + "token": "USDC", + "chain": "ethereum" + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("transaction.created".to_string()), + None, + Some(&defi_payload), + ); + + // Only DeFi endpoint should pass + assert_eq!(filtered_endpoints.len(), 1); + assert_eq!(filtered_endpoints[0].id, EndpointId::from("defi_endpoint".to_string())); + + // Test NFT transaction that should pass + let nft_payload = json!({ + "price": 5.5, + "collection": "BoredApe", + "tokenId": 1234 + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("nft.sold".to_string()), + None, + Some(&nft_payload), + ); + + // Only NFT endpoint should pass + assert_eq!(filtered_endpoints.len(), 1); + assert_eq!(filtered_endpoints[0].id, EndpointId::from("nft_endpoint".to_string())); + + // Test transaction that should fail both filters + let low_value_payload = json!({ + "amount": 500.0, // Below DeFi threshold + "price": 0.5, // Below NFT threshold + "token": "USDC", + "collection": "BoredApe" + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("transaction.created".to_string()), + None, + Some(&low_value_payload), + ); + + // No endpoints should pass + assert_eq!(filtered_endpoints.len(), 0); + } + + #[test] + fn test_cel_filter_real_integration_complex_conditions() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Create endpoint with complex multi-condition filter + let complex_endpoint = CreateMessageEndpoint { + id: EndpointId::from("complex_endpoint".to_string()), + url: "https://example.com/complex".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("balance >= 1000.0 && status == 'active' && verified == true".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints: vec![complex_endpoint], + deleted: false, + }; + + // Test payload that should pass all conditions + let valid_payload = json!({ + "balance": 1500.0, + "status": "active", + "verified": true + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&valid_payload), + ); + + // Should pass the complex filter + assert_eq!(filtered_endpoints.len(), 1); + assert_eq!(filtered_endpoints[0].id, EndpointId::from("complex_endpoint".to_string())); + + // Test payload that fails one condition (balance too low) + let invalid_balance_payload = json!({ + "balance": 500.0, // Below threshold + "status": "active", + "verified": true + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&invalid_balance_payload), + ); + + // Should fail the complex filter + assert_eq!(filtered_endpoints.len(), 0); + + // Test payload that fails another condition (status inactive) + let invalid_status_payload = json!({ + "balance": 1500.0, + "status": "inactive", // Wrong status + "verified": true + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("user.created".to_string()), + None, + Some(&invalid_status_payload), + ); + + // Should fail the complex filter + assert_eq!(filtered_endpoints.len(), 0); + } + + #[test] + fn test_cel_filter_real_integration_performance_large_payload() { + use crate::core::types::{ApplicationId, EventTypeName, MessageAttemptTriggerType, OrganizationId}; + use serde_json::json; + + // Create endpoint with deep nested filter + let deep_nested_endpoint = CreateMessageEndpoint { + id: EndpointId::from("deep_nested_endpoint".to_string()), + url: "https://example.com/deep".to_string(), + key: EndpointSecretInternal::from_endpoint_secret( + EndpointSecret::Symmetric(STANDARD.decode("MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw").unwrap()), + &Encryption::new_noop(), + ).unwrap(), + old_signing_keys: None, + event_types_ids: None, + channels: None, + filter: Some("level1.level2.level3.level4.level5.value == 42.0".to_string()), + rate_limit: None, + first_failure_at: None, + headers: None, + disabled: false, + deleted: false, + }; + + let create_message_app = CreateMessageApp { + id: ApplicationId::from("test_app".to_string()), + uid: None, + org_id: OrganizationId::from("test_org".to_string()), + rate_limit: None, + endpoints: vec![deep_nested_endpoint], + deleted: false, + }; + + // Test with large nested payload + let large_payload = json!({ + "level1": { + "level2": { + "level3": { + "level4": { + "level5": { + "value": 42.0, + "name": "deep_value" + } + } + } + } + }, + "metadata": { + "source": "test", + "timestamp": "2024-01-01T00:00:00Z" + } + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("deep.test".to_string()), + None, + Some(&large_payload), + ); + + // Should pass the deep nested filter + assert_eq!(filtered_endpoints.len(), 1); + assert_eq!(filtered_endpoints[0].id, EndpointId::from("deep_nested_endpoint".to_string())); + + // Test with wrong value + let wrong_value_payload = json!({ + "level1": { + "level2": { + "level3": { + "level4": { + "level5": { + "value": 100.0, // Wrong value + "name": "deep_value" + } + } + } + } + } + }); + + let filtered_endpoints = create_message_app.filtered_endpoints( + MessageAttemptTriggerType::Scheduled, + &EventTypeName::from("deep.test".to_string()), + None, + Some(&wrong_value_payload), + ); + + // Should fail the deep nested filter + assert_eq!(filtered_endpoints.len(), 0); + } + + #[test] + fn test_validate_cel_expression() { + use super::validate_cel_expression; + // Test valid expressions + assert!(validate_cel_expression("age >= 18").is_ok()); + assert!(validate_cel_expression("status == 'active'").is_ok()); + assert!(validate_cel_expression("verified == true").is_ok()); + assert!(validate_cel_expression("balance >= 1000.0 && status == 'active'").is_ok()); + assert!(validate_cel_expression("").is_ok()); + assert!(validate_cel_expression(" ").is_ok()); + + assert!(validate_cel_expression("age >= ").is_err()); + assert!(validate_cel_expression("age >= 18 &&").is_err()); + } + + #[test] + fn test_validate_cel_expression_length_limit() { + use super::validate_cel_expression; + + // Test valid length + let short_expr = "age >= 18"; + assert!(validate_cel_expression(short_expr).is_ok()); + + // Test length limit + let long_expr = "a".repeat(2500); // Create a string longer than 2048 + let result = validate_cel_expression(&long_expr); + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.contains("CEL expression too long")); + assert!(error.contains("max: 2048")); + } + + #[test] + fn test_validate_cel_expression_complexity_limit() { + use super::validate_cel_expression; + + // Test valid complexity + let simple_expr = "age >= 18 && status == 'active'"; + assert!(validate_cel_expression(simple_expr).is_ok()); + + // Test complexity limit with many operators (but keep under length limit) + let complex_expr = (0..25) + .map(|i| format!("f{}>=1.0&&f{}=='v{}'", i, i, i)) + .collect::>() + .join("&&"); + + let result = validate_cel_expression(&complex_expr); + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.contains("CEL expression too complex")); + assert!(error.contains("max: 50")); + } + + #[test] + fn test_calculate_cel_complexity() { + use super::calculate_cel_complexity; + + // Test simple expressions + assert_eq!(calculate_cel_complexity("age >= 18"), 1); // >= operator + assert_eq!(calculate_cel_complexity("name == 'test'"), 4); // ==, ., and string + assert_eq!(calculate_cel_complexity("age >= 18 && status == 'active'"), 7); // >=, &&, ==, ., string + + // Test complex expressions + let complex = "a.b.c >= 1.0 && x.y.z == 'test' && p.q == true"; + let complexity = calculate_cel_complexity(complex); + assert!(complexity > 10); // Should have high complexity + + // Test empty expression + assert_eq!(calculate_cel_complexity(""), 0); + assert_eq!(calculate_cel_complexity(" "), 0); + } + + #[cfg(debug_assertions)] + #[test] + fn test_cel_execution_metrics() { + use super::{CelExecutionMetrics, CEL_EXECUTION_WARNING_THRESHOLD_MS, CEL_EXECUTION_ERROR_THRESHOLD_MS}; + + // Test successful execution metrics + let metrics = CelExecutionMetrics::new( + "age >= 18".to_string(), + 5, // 5ms execution time + 3, // complexity + true, // success + None, // no error + ); + + assert_eq!(metrics.expression, "age >= 18"); + assert_eq!(metrics.execution_time_ms, 5); + assert_eq!(metrics.complexity, 3); + assert!(metrics.success); + assert!(metrics.error_message.is_none()); + + // Test warning threshold metrics + let warning_metrics = CelExecutionMetrics::new( + "complex.expression".to_string(), + CEL_EXECUTION_WARNING_THRESHOLD_MS + 5, // Above warning threshold + 20, + true, + None, + ); + + assert!(warning_metrics.execution_time_ms >= CEL_EXECUTION_WARNING_THRESHOLD_MS); + + // Test error threshold metrics + let error_metrics = CelExecutionMetrics::new( + "very.complex.expression".to_string(), + CEL_EXECUTION_ERROR_THRESHOLD_MS + 10, // Above error threshold + 50, + false, + Some("Compilation failed".to_string()), + ); + + assert!(error_metrics.execution_time_ms >= CEL_EXECUTION_ERROR_THRESHOLD_MS); + assert!(!error_metrics.success); + assert!(error_metrics.error_message.is_some()); + } } diff --git a/server/svix-server/src/db/models/endpoint.rs b/server/svix-server/src/db/models/endpoint.rs index 0c44aece9..d859c9d12 100644 --- a/server/svix-server/src/db/models/endpoint.rs +++ b/server/svix-server/src/db/models/endpoint.rs @@ -35,6 +35,8 @@ pub struct Model { pub old_keys: Option, pub channels: Option, pub headers: Option, + /// Optional CEL filter expression applied to payloads at dispatch time + pub filter: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/server/svix-server/src/v1/endpoints/endpoint/crud.rs b/server/svix-server/src/v1/endpoints/endpoint/crud.rs index ee420bce3..e125f213c 100644 --- a/server/svix-server/src/v1/endpoints/endpoint/crud.rs +++ b/server/svix-server/src/v1/endpoints/endpoint/crud.rs @@ -13,6 +13,7 @@ use super::{EndpointIn, EndpointOut, EndpointPatch, EndpointUpdate}; use crate::{ cfg::Configuration, core::{ + message_app::validate_cel_expression, operational_webhooks::{EndpointEvent, OperationalWebhook, OperationalWebhookSender}, permissions, types::{EndpointId, EventTypeName, EventTypeNameSet, OrganizationId}, @@ -76,6 +77,17 @@ async fn create_endp_from_data( app: application::Model, mut data: EndpointIn, ) -> Result<(endpoint::Model, endpointmetadata::Model)> { + // Validate CEL expression if provided + if let Some(ref filter) = data.filter { + if let Err(e) = validate_cel_expression(filter) { + return Err(HttpError::unprocessable_entity(vec![ValidationErrorItem { + loc: vec!["filter".to_string()], + msg: format!("Invalid CEL expression: {}", e), + ty: "value_error".to_string(), + }]).into()); + } + } + let key = data.key_take_or_generate(&cfg.encryption, &cfg.default_signature_type)?; let mut endp = endpoint::ActiveModel::new(app.id, key); @@ -189,6 +201,17 @@ pub(super) async fn update_endpoint( validate_event_types(db, event_types_ids, &app.org_id).await?; } validate_endpoint_url(&data.url, cfg.endpoint_https_only)?; + + // Validate CEL expression if provided + if let Some(ref filter) = data.filter { + if let Err(e) = validate_cel_expression(filter) { + return Err(HttpError::unprocessable_entity(vec![ValidationErrorItem { + loc: vec!["filter".to_string()], + msg: format!("Invalid CEL expression: {}", e), + ty: "value_error".to_string(), + }]).into()); + } + } let models = endpoint::ActiveModel::fetch_with_metadata(db, app.id.clone(), endpoint_id) .await @@ -229,6 +252,17 @@ pub(super) async fn patch_endpoint( if let UnrequiredField::Some(url) = &data.url { validate_endpoint_url(url, cfg.endpoint_https_only)?; } + + // Validate CEL expression if provided + if let UnrequiredNullableField::Some(ref filter) = data.filter { + if let Err(e) = validate_cel_expression(filter) { + return Err(HttpError::unprocessable_entity(vec![ValidationErrorItem { + loc: vec!["filter".to_string()], + msg: format!("Invalid CEL expression: {}", e), + ty: "value_error".to_string(), + }]).into()); + } + } let (mut endp, mut metadata) = endpoint::ActiveModel::fetch_with_metadata(db, app.id.clone(), endpoint_id) diff --git a/server/svix-server/src/v1/endpoints/endpoint/mod.rs b/server/svix-server/src/v1/endpoints/endpoint/mod.rs index f0f239bae..4c65067a9 100644 --- a/server/svix-server/src/v1/endpoints/endpoint/mod.rs +++ b/server/svix-server/src/v1/endpoints/endpoint/mod.rs @@ -188,6 +188,10 @@ pub struct EndpointIn { #[serde(default)] pub metadata: Metadata, + + /// Optional CEL boolean expression to filter messages by payload + #[serde(skip_serializing_if = "Option::is_none")] + pub filter: Option, } impl EndpointIn { @@ -221,6 +225,7 @@ impl ModelIn for EndpointIn { channels, key: _, metadata: _, + filter, } = self; model.description = Set(description); @@ -231,6 +236,7 @@ impl ModelIn for EndpointIn { model.disabled = Set(disabled); model.event_types_ids = Set(event_types_ids); model.channels = Set(channels); + model.filter = Set(filter); } } @@ -279,6 +285,10 @@ struct EndpointUpdate { #[serde(default)] pub metadata: Metadata, + + /// Optional CEL boolean expression to filter messages by payload + #[serde(skip_serializing_if = "Option::is_none")] + pub filter: Option, } impl ModelIn for EndpointUpdate { @@ -296,6 +306,7 @@ impl ModelIn for EndpointUpdate { event_types_ids, channels, metadata: _, + filter, } = self; model.description = Set(description); @@ -306,6 +317,7 @@ impl ModelIn for EndpointUpdate { model.disabled = Set(disabled); model.event_types_ids = Set(event_types_ids); model.channels = Set(channels); + model.filter = Set(filter); } } @@ -322,6 +334,7 @@ impl EndpointUpdate { event_types_ids, channels, metadata, + filter, } = self; EndpointIn { @@ -334,6 +347,7 @@ impl EndpointUpdate { event_types_ids, channels, metadata, + filter, key: None, } @@ -390,6 +404,10 @@ pub struct EndpointPatch { #[serde(default)] #[serde(skip_serializing_if = "UnrequiredField::is_absent")] pub metadata: UnrequiredField, + + #[serde(default)] + #[serde(skip_serializing_if = "UnrequiredNullableField::is_absent")] + pub filter: UnrequiredNullableField, } impl ModelIn for EndpointPatch { @@ -408,6 +426,7 @@ impl ModelIn for EndpointPatch { channels, key: _, metadata: _, + filter, } = self; let map = |x: u16| -> i32 { x.into() }; @@ -421,6 +440,7 @@ impl ModelIn for EndpointPatch { patch_field_non_nullable!(model, disabled); patch_field_nullable!(model, event_types_ids); patch_field_nullable!(model, channels); + patch_field_nullable!(model, filter); } } @@ -482,6 +502,7 @@ pub struct EndpointOutCommon { /// List of message channels this endpoint listens to (omit for all) #[schemars(example = "example_channel_set", length(min = 1, max = 10))] pub channels: Option, + pub filter: Option, pub created_at: DateTime, pub updated_at: DateTime, } @@ -498,6 +519,7 @@ impl From for EndpointOutCommon { disabled: model.disabled, event_types_ids: model.event_types_ids, channels: model.channels, + filter: model.filter, created_at: model.created_at.into(), updated_at: model.updated_at.into(), } diff --git a/server/svix-server/src/v1/endpoints/message.rs b/server/svix-server/src/v1/endpoints/message.rs index 58b5d5434..664174ddf 100644 --- a/server/svix-server/src/v1/endpoints/message.rs +++ b/server/svix-server/src/v1/endpoints/message.rs @@ -392,8 +392,12 @@ pub(crate) async fn create_message_inner( .await?; let trigger_type = MessageAttemptTriggerType::Scheduled; + // Parse payload from legacy_payload for filtering + let payload_json = msg.legacy_payload.as_ref() + .and_then(|p| serde_json::to_value(p).ok()); + if !create_message_app - .filtered_endpoints(trigger_type, &msg.event_type, msg.channels.as_ref()) + .filtered_endpoints(trigger_type, &msg.event_type, msg.channels.as_ref(), payload_json.as_ref()) .is_empty() { queue_tx diff --git a/server/svix-server/src/worker.rs b/server/svix-server/src/worker.rs index f7a3a000a..3b6d359e2 100644 --- a/server/svix-server/src/worker.rs +++ b/server/svix-server/src/worker.rs @@ -855,8 +855,10 @@ async fn process_queue_task_inner( return Ok(()); }; + let payload_json: Option = serde_json::from_str(&payload).ok(); + let endpoints: Vec = create_message_app - .filtered_endpoints(trigger_type, &msg.event_type, msg.channels.as_ref()) + .filtered_endpoints(trigger_type, &msg.event_type, msg.channels.as_ref(), payload_json.as_ref()) .iter() .filter(|endpoint| match force_endpoint.as_ref() { Some(endp_id) => endp_id == &endpoint.id,