diff --git a/.github/workflows/test-eql.yml b/.github/workflows/test-eql.yml index 73e5ab37..9527faa8 100644 --- a/.github/workflows/test-eql.yml +++ b/.github/workflows/test-eql.yml @@ -64,6 +64,10 @@ jobs: env: POSTGRES_VERSION: ${{ matrix.postgres-version }} + CS_CLIENT_ACCESS_KEY: ${{ secrets.CS_CLIENT_ACCESS_KEY }} + CS_WORKSPACE_CRN: ${{ secrets.CS_WORKSPACE_CRN }} + CS_CLIENT_ID: ${{ secrets.CS_CLIENT_ID }} + CS_CLIENT_KEY: ${{ secrets.CS_CLIENT_KEY }} steps: - uses: actions/checkout@v6 @@ -126,4 +130,3 @@ jobs: mise run --output prefix test:splinter --postgres ${POSTGRES_VERSION} - diff --git a/.gitignore b/.gitignore index d9a13a2e..68bca65b 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,10 @@ web_modules/ .env.local .envrc +# Local mise overrides (CipherStash credentials, etc.) +mise.local.toml +.mise.local.toml + # parcel-bundler cache (https://parceljs.org/) .parcel-cache @@ -215,6 +219,10 @@ eql--*.sql # Generated SQLx migration (built from src/, never commit) tests/sqlx/migrations/001_install_eql.sql +# Generated SQLx fixtures (regenerated via `mise run fixture:generate`, +# never commit — stale fixtures hide bugs) +tests/sqlx/fixtures/eql_v2_int4.sql + # Large generated test data files tests/ste_vec_vast.sql tests/ste_vec_*M.sql* @@ -225,6 +233,7 @@ tests/sqlx/target/ # Work files (agent-generated, not for version control) .work/ .serena/ +docs/superpowers/ # Build variants - protect variant deps src/deps-protect.txt diff --git a/mise.toml b/mise.toml index fbf499b4..1cd33881 100644 --- a/mise.toml +++ b/mise.toml @@ -14,7 +14,7 @@ "python" = "3.13" [task_config] -includes = ["tasks", "tasks/postgres.toml"] +includes = ["tasks", "tasks/postgres.toml", "tasks/fixtures.toml"] [env] POSTGRES_DB = "cipherstash" @@ -34,6 +34,11 @@ run = """ [tasks."test:sqlx"] description = "Run SQLx tests with hybrid migration approach" +# `build` produces release/cipherstash-encrypt.sql, which is then cp'd into +# tests/sqlx/migrations/001_install_eql.sql below. Without this dep, a stale +# release artifact silently ships an old EQL extension into the test DB and +# regression-guard migrations (e.g. 003_install_ste_vec_data.sql) fail. +depends = ["build"] dir = "{{config_root}}" run = """ # Copy built SQL to SQLx migrations (EQL install is generated, not static) @@ -45,7 +50,18 @@ echo "Running SQLx migrations..." cd tests/sqlx sqlx migrate run +# Regenerate fixtures every run — they are not committed (see .gitignore). +# Generator encrypts via cipherstash-client directly, which needs BOTH a +# ZeroKMS auth credential (CS_CLIENT_ACCESS_KEY + CS_WORKSPACE_CRN, via +# AutoStrategy) AND a client key (CS_CLIENT_ID + CS_CLIENT_KEY, via +# EnvKeyProvider) in the shell environment. Auth and key material are +# separate roles — the two pairs are not alternatives. +echo "Regenerating SQLx fixtures..." +cd "{{config_root}}" +mise run fixture:generate eql_v2_int4 + echo "Running Rust tests..." +cd tests/sqlx cargo test """ diff --git a/tasks/fixtures.toml b/tasks/fixtures.toml new file mode 100644 index 00000000..be0d6fd1 --- /dev/null +++ b/tasks/fixtures.toml @@ -0,0 +1,25 @@ +["fixture:generate"] +description = "Generate a SQLx fixture script via cipherstash-client" +# Runs the gated generator for the named fixture. Writes +# tests/sqlx/fixtures/.sql. Must run inside the crate — there is no +# root Cargo.toml — matching test:schema / test:sqlx:watch. +# +# Prerequisites: +# - mise run postgres:up (Postgres with EQL installed) +# - CS_* credentials in the shell environment. The generator needs BOTH +# pairs — they are not alternatives: +# CS_CLIENT_ACCESS_KEY + CS_WORKSPACE_CRN ZeroKMS auth (AutoStrategy) +# CS_CLIENT_ID + CS_CLIENT_KEY client key (EnvKeyProvider) +# +# Usage: mise run fixture:generate eql_v2_int4 +dir = "{{config_root}}/tests/sqlx" +run = """ +fixture="{{arg(name="fixture")}}" +case "$fixture" in + (*[!a-z0-9_]*|'') echo "Invalid fixture name: $fixture (expected [a-z0-9_]+)" >&2; exit 1 ;; +esac + +cargo test --features fixture-gen --lib \ + "fixtures::${fixture}::generate" \ + -- --ignored --exact --nocapture +""" diff --git a/tests/sqlx/Cargo.lock b/tests/sqlx/Cargo.lock index db86aeba..e39e030b 100644 --- a/tests/sqlx/Cargo.lock +++ b/tests/sqlx/Cargo.lock @@ -2,6 +2,84 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.6", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", + "zeroize", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", + "zeroize", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.12" @@ -25,18 +103,104 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "aquamarine" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "async-compression" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +dependencies = [ + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-mutex" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73112ce9e1059d8604242af62c7ec8e5975ac58ac251686c8403b45e8a6fe778" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "atoi" version = "2.0.0" @@ -46,12 +210,86 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base32" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" + [[package]] name = "base64" version = "0.22.1" @@ -64,6 +302,15 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +[[package]] +name = "base85" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36915bbaca237c626689b5bd14d02f2ba7a5a359d30a2a08be697392e3718079" +dependencies = [ + "thiserror 1.0.69", +] + [[package]] name = "bit-set" version = "0.8.0" @@ -81,13 +328,40 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", + "zeroize", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -97,24 +371,112 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block-modes" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2211b0817f061502a8dd9f11a37e879e79763e3c698d2418cf824d8cb2f21e" + [[package]] name = "borrow-or-share" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "brotli" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytecount" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + [[package]] name = "byteorder" version = "1.5.0" @@ -126,1036 +488,2802 @@ name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] [[package]] -name = "cfg-if" -version = "1.0.4" +name = "cached" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "9718806c4a2fe9e8a56fd736f97b340dd10ed1be8ed733ed50449f351dc33cae" +dependencies = [ + "ahash 0.8.12", + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.14.5", + "once_cell", + "thiserror 1.0.69", + "web-time", +] [[package]] -name = "concurrent-queue" -version = "2.5.0" +name = "cached_proc_macro" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa" dependencies = [ - "crossbeam-utils", + "darling", + "proc-macro2", + "quote", + "syn 2.0.108", ] [[package]] -name = "const-oid" -version = "0.9.6" +name = "cached_proc_macro_types" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" [[package]] -name = "cpufeatures" -version = "0.2.17" +name = "cc" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ + "find-msvc-tools", + "jobserver", "libc", + "shlex", ] [[package]] -name = "crc" -version = "3.3.0" +name = "cfg-if" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "crc-catalog" -version = "2.4.0" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "crossbeam-queue" -version = "0.3.12" +name = "chacha20" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ - "crossbeam-utils", + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", ] [[package]] -name = "crossbeam-utils" -version = "0.8.21" +name = "chrono" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "generic-array", - "typenum", + "iana-time-zone", + "num-traits", + "serde", + "windows-link", ] [[package]] -name = "data-encoding" -version = "2.11.0" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common 0.1.6", + "inout", +] [[package]] -name = "der" -version = "0.7.10" +name = "cipherstash-client" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +checksum = "0257cff25a25a706af6e190e5209865aae4ddf0b36f81febee7de014b22bcc40" dependencies = [ - "const-oid", - "pem-rfc7468", + "aes-gcm-siv", + "anyhow", + "async-mutex", + "async-trait", + "base16ct", + "base64", + "base85", + "blake3", + "chrono", + "cipherstash-config", + "cipherstash-core", + "cllw-ore", + "cts-common", + "derive_more 1.0.0", + "dirs", + "futures", + "hex", + "hmac", + "itertools 0.12.1", + "lazy_static", + "log", + "miette", + "opaque-debug", + "orderable-bytes", + "ore-rs", + "percent-encoding", + "rand 0.8.6", + "recipher", + "reqwest", + "rmp-serde", + "rust-stemmers", + "rust_decimal", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "serdect", + "sha2", + "stack-auth", + "stack-profile", + "static_assertions", + "thiserror 1.0.69", + "tokio", + "toml", + "tracing", + "url", + "uuid", + "vitaminc", + "vitaminc-protected", + "winnow 0.6.26", "zeroize", + "zerokms-protocol", ] [[package]] -name = "digest" -version = "0.10.7" +name = "cipherstash-config" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "d376d237e368e77de53b07bb7309812f45809299063c80b6cc3132f7d8494aed" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", + "bitflags", + "serde", + "serde_json", + "thiserror 1.0.69", ] [[package]] -name = "displaydoc" -version = "0.2.5" +name = "cipherstash-core" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "ca84ffd8a7b2f0c8c6b04eba600738fea115f5a4ed825035a2f13aa1524085a7" dependencies = [ - "proc-macro2", - "quote", - "syn", + "getrandom 0.2.16", + "hmac", + "lazy_static", + "num-bigint", + "rand 0.8.6", + "regex", + "sha2", + "thiserror 1.0.69", ] [[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "either" -version = "1.15.0" +name = "cllw-ore" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "4f73a23cbc15404d9b314c03b16a888f798dbc681bceeb2e18674f602f9da02d" dependencies = [ - "serde", + "blake3", + "chrono", + "hex", + "orderable-bytes", + "rust_decimal", + "subtle", + "thiserror 1.0.69", + "unicode-normalization", ] [[package]] -name = "email_address" -version = "0.2.9" +name = "cmac" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" +checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" dependencies = [ - "serde", + "cipher", + "dbl", + "digest 0.10.7", ] [[package]] -name = "eql_tests" -version = "0.1.0" +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ - "anyhow", - "hex", - "jsonschema", - "serde", - "serde_json", - "sqlx", - "tokio", + "cc", ] [[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "etcetera" -version = "0.8.0" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", + "bytes", + "memchr", ] [[package]] -name = "event-listener" -version = "5.4.1" +name = "compression-codecs" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", + "brotli", + "compression-core", + "flate2", + "memchr", ] [[package]] -name = "fancy-regex" -version = "0.18.0" +name = "compression-core" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" -dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", -] +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" [[package]] -name = "fluent-uri" -version = "0.4.1" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "borrow-or-share", - "ref-cast", - "serde", + "crossbeam-utils", ] [[package]] -name = "flume" -version = "0.11.1" +name = "const-hex" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558" dependencies = [ - "futures-core", - "futures-sink", - "spin", + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", ] [[package]] -name = "foldhash" -version = "0.1.5" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "foldhash" -version = "0.2.0" +name = "constant_time_eq" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] -name = "form_urlencoded" -version = "1.2.2" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ - "percent-encoding", + "unicode-segmentation", ] [[package]] -name = "fraction" -version = "0.15.4" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ - "lazy_static", - "num", + "core-foundation-sys", + "libc", ] [[package]] -name = "futures-channel" -version = "0.3.31" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "futures-core" -version = "0.3.31" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] [[package]] -name = "futures-executor" -version = "0.3.31" +name = "cpufeatures" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ - "futures-core", - "futures-task", - "futures-util", + "libc", ] [[package]] -name = "futures-intrusive" -version = "0.5.0" +name = "crc" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ - "futures-core", - "lock_api", - "parking_lot", + "crc-catalog", ] [[package]] -name = "futures-io" -version = "0.3.31" +name = "crc-catalog" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "futures-sink" -version = "0.3.31" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] [[package]] -name = "futures-task" -version = "0.3.31" +name = "critical-section" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] -name = "futures-util" -version = "0.3.31" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", + "crossbeam-utils", ] [[package]] -name = "generic-array" -version = "0.14.9" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "typenum", - "version_check", + "crossbeam-utils", ] [[package]] -name = "getrandom" -version = "0.2.16" +name = "crossbeam-queue" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "cfg-if", - "libc", - "wasi", + "crossbeam-utils", ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasip2", - "wasm-bindgen", + "generic-array", + "rand_core 0.6.4", + "typenum", ] [[package]] -name = "hashbrown" -version = "0.15.5" +name = "crypto-common" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.1.5", + "hybrid-array", ] [[package]] -name = "hashbrown" -version = "0.16.0" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", + "cipher", ] [[package]] -name = "hashlink" -version = "0.10.0" +name = "cts-common" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ae6508011dee61bc36e16615e43cb26a8014c49ebb832e713602f3b0dc15af29" dependencies = [ - "hashbrown 0.15.5", + "arrayvec", + "base32", + "cached", + "chrono", + "derive_more 2.1.1", + "either", + "getrandom 0.4.2", + "miette", + "nom", + "regex", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "url", + "utoipa", + "uuid", + "vitaminc", ] [[package]] -name = "heck" -version = "0.5.0" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] [[package]] -name = "hex" -version = "0.4.3" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.108", +] [[package]] -name = "hkdf" -version = "0.12.4" +name = "darling_macro" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "hmac", + "darling_core", + "quote", + "syn 2.0.108", ] [[package]] -name = "hmac" -version = "0.12.1" +name = "data-encoding" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "dbl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" dependencies = [ - "digest", + "generic-array", ] [[package]] -name = "home" -version = "0.5.11" +name = "der" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "windows-sys 0.59.0", + "const-oid", + "pem-rfc7468", + "zeroize", ] [[package]] -name = "icu_collections" -version = "2.0.0" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", + "powerfmt", ] [[package]] -name = "icu_locale_core" -version = "2.0.0" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "derive_more-impl 1.0.0", ] [[package]] -name = "icu_normalizer" -version = "2.0.0" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", + "derive_more-impl 2.1.1", ] [[package]] -name = "icu_normalizer_data" -version = "2.0.0" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "unicode-xid", +] [[package]] -name = "icu_properties" -version = "2.0.1" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.108", + "unicode-xid", ] [[package]] -name = "icu_properties_data" -version = "2.0.1" +name = "deunicode" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" [[package]] -name = "icu_provider" -version = "2.0.0" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", + "block-buffer 0.10.4", + "const-oid", + "crypto-common 0.1.6", + "subtle", ] [[package]] -name = "idna" -version = "1.1.0" +name = "digest" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", + "block-buffer 0.12.0", + "crypto-common 0.2.2", ] [[package]] -name = "idna_adapter" -version = "1.2.1" +name = "dirs" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "icu_normalizer", - "icu_properties", + "dirs-sys", ] [[package]] -name = "indexmap" -version = "2.12.0" +name = "dirs-sys" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ - "equivalent", - "hashbrown 0.16.0", + "libc", + "redox_users", + "winapi", ] [[package]] -name = "itoa" -version = "1.0.15" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] [[package]] -name = "js-sys" -version = "0.3.98" +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dummy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac124e13ae9aa56acc4241f8c8207501d93afdd8d8e62f0c1f2e12f6508c65" dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen", + "darling", + "proc-macro2", + "quote", + "syn 2.0.108", ] [[package]] -name = "jsonschema" -version = "0.46.4" +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc59d2432e047d6090ba1d83c782d0128bd6203857978218f5614dbd3287281f" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ - "ahash", - "bytecount", - "data-encoding", - "email_address", - "fancy-regex", - "fraction", - "getrandom 0.3.4", - "idna", - "itoa", - "num-cmp", - "num-traits", - "percent-encoding", - "referencing", - "regex", - "regex-syntax", "serde", - "serde_json", - "unicode-general-category", - "uuid-simd", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "email_address" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" dependencies = [ - "spin", + "serde", ] [[package]] -name = "libc" -version = "0.2.177" +name = "enum-as-inner" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.108", +] [[package]] -name = "libm" -version = "0.2.15" +name = "eql_tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "cipherstash-client", + "hex", + "jsonschema", + "serde", + "serde_json", + "sqlx", + "tokio", +] + +[[package]] +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "libredox" -version = "0.1.10" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "bitflags", "libc", - "redox_syscall", + "windows-sys 0.61.2", ] [[package]] -name = "libsqlite3-sys" -version = "0.30.1" +name = "etcetera" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "pkg-config", - "vcpkg", + "cfg-if", + "home", + "windows-sys 0.48.0", ] [[package]] -name = "litemap" -version = "0.8.0" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] -name = "lock_api" -version = "0.4.14" +name = "event-listener" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ - "scopeguard", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "log" -version = "0.4.28" +name = "fake" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "2d391ba4af7f1d93f01fcf7b2f29e2bc9348e109dfdbf4dcbdc51dfa38dab0b6" +dependencies = [ + "deunicode", + "dummy", + "rand 0.8.6", + "uuid", +] + +[[package]] +name = "fancy-regex" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fluent-uri" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +dependencies = [ + "borrow-or-share", + "ref-cast", + "serde", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fraction" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +dependencies = [ + "lazy_static", + "num", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" +dependencies = [ + "rustix 0.38.44", + "windows-targets 0.52.6", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.12", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.4", + "ring", + "thiserror 2.0.18", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.4", + "resolv-conf", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipconfig" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" +dependencies = [ + "socket2", + "widestring", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.108", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.108", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonschema" +version = "0.46.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc59d2432e047d6090ba1d83c782d0128bd6203857978218f5614dbd3287281f" +dependencies = [ + "ahash 0.8.12", + "bytecount", + "data-encoding", + "email_address", + "fancy-regex", + "fraction", + "getrandom 0.3.4", + "idna", + "itoa", + "num-cmp", + "num-traits", + "percent-encoding", + "referencing", + "regex", + "regex-syntax", + "serde", + "serde_json", + "unicode-general-category", + "uuid-simd", +] + +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "micromap" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moka" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.6", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "open" +version = "5.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "orderable-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adba0469737879cabc3bdcaa6a7beb4ff7f5bb4aa5d624816c8bb9d425a7d5df" +dependencies = [ + "chrono", + "rust_decimal", +] + +[[package]] +name = "ore-rs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77fb65718f1aba7bb7f568db90a2b17a48871d83cd9d1101d19fce449dd8dea" +dependencies = [ + "aes", + "block-modes", + "byteorder", + "chrono", + "hex", + "lazy_static", + "num", + "orderable-bytes", + "rand 0.8.6", + "rand_chacha 0.3.1", + "rust_decimal", + "subtle-ng", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", - "digest", + "libc", + "redox_syscall", + "smallvec", + "windows-link", ] [[package]] -name = "memchr" -version = "2.7.6" +name = "pathdiff" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] -name = "micromap" -version = "0.3.0" +name = "pem" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] [[package]] -name = "mio" -version = "1.1.0" +name = "pem-rfc7468" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", + "base64ct", ] [[package]] -name = "num" -version = "0.4.3" +name = "percent-encoding" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.6+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro2" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bitflags", "num-traits", + "rand 0.9.4", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +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 = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] -name = "num-bigint" -version = "0.4.6" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "num-integer", - "num-traits", + "getrandom 0.2.16", ] [[package]] -name = "num-bigint-dig" -version = "0.8.6" +name = "rand_core" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", + "getrandom 0.3.4", ] [[package]] -name = "num-cmp" -version = "0.1.0" +name = "rand_core" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] -name = "num-complex" -version = "0.4.6" +name = "rand_xorshift" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "num-traits", + "rand_core 0.9.5", ] [[package]] -name = "num-integer" -version = "0.1.46" +name = "recipher" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "9398dce78ddfce08f93e9d9a3ac64d9b0a4fed478c0a82003c6e4c90dc245125" dependencies = [ - "num-traits", + "aes", + "cmac", + "getrandom 0.2.16", + "hex", + "hex-literal", + "opaque-debug", + "rand 0.8.6", + "rand_chacha 0.3.1", + "serde", + "serde_cbor", + "sha2", + "thiserror 1.0.69", + "zeroize", ] [[package]] -name = "num-iter" -version = "0.1.45" +name = "redox_syscall" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "autocfg", - "num-integer", - "num-traits", + "bitflags", ] [[package]] -name = "num-rational" -version = "0.4.2" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "num-bigint", - "num-integer", - "num-traits", + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "autocfg", - "libm", + "ref-cast-impl", ] [[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "outref" -version = "0.5.2" +name = "ref-cast-impl" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] [[package]] -name = "parking" -version = "2.2.1" +name = "referencing" +version = "0.46.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "cb674900ca31acd75c4aaf63f48e43e719631c0539ea5a9e64163d1296bcb730" +dependencies = [ + "ahash 0.8.12", + "fluent-uri", + "getrandom 0.3.4", + "hashbrown 0.16.0", + "itoa", + "micromap", + "parking_lot", + "percent-encoding", + "serde_json", +] [[package]] -name = "parking_lot" -version = "0.12.5" +name = "regex" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ - "lock_api", - "parking_lot_core", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "parking_lot_core" -version = "0.9.12" +name = "regex-automata" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "pem-rfc7468" -version = "0.7.0" +name = "regex-syntax" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "percent-encoding" -version = "2.3.2" +name = "rend" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] [[package]] -name = "pin-project-lite" -version = "0.2.16" +name = "reqwest" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "hickory-resolver", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "resolv-conf" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] -name = "pkcs1" -version = "0.7.5" +name = "ring" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ - "der", - "pkcs8", - "spki", + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", ] [[package]] -name = "pkcs8" -version = "0.10.2" +name = "rkyv" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" dependencies = [ - "der", - "spki", + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", ] [[package]] -name = "pkg-config" -version = "0.3.32" +name = "rkyv_derive" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] -name = "potential_utf" -version = "0.1.3" +name = "rmp" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "zerovec", + "num-traits", ] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "rmp-serde" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" dependencies = [ - "zerocopy", + "rmp", + "serde", ] [[package]] -name = "proc-macro2" -version = "1.0.102" +name = "rsa" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ - "unicode-ident", + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", ] [[package]] -name = "quote" -version = "1.0.41" +name = "rust-stemmers" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" dependencies = [ - "proc-macro2", + "serde", + "serde_derive", ] [[package]] -name = "r-efi" -version = "5.3.0" +name = "rust_decimal" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] [[package]] -name = "rand" -version = "0.8.6" +name = "rustc-demangle" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rustc-hash" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] -name = "rand_core" -version = "0.6.4" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "getrandom 0.2.16", + "semver", ] [[package]] -name = "redox_syscall" -version = "0.5.18" +name = "rustix" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] -name = "ref-cast" -version = "1.0.25" +name = "rustix" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "ref-cast-impl", + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] -name = "ref-cast-impl" -version = "1.0.25" +name = "rustls" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] -name = "referencing" -version = "0.46.4" +name = "rustls-native-certs" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb674900ca31acd75c4aaf63f48e43e719631c0539ea5a9e64163d1296bcb730" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "ahash", - "fluent-uri", - "getrandom 0.3.4", - "hashbrown 0.16.0", - "itoa", - "micromap", - "parking_lot", - "percent-encoding", - "serde_json", + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", ] [[package]] -name = "regex" -version = "1.12.3" +name = "rustls-pki-types" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "web-time", + "zeroize", ] [[package]] -name = "regex-automata" -version = "0.4.14" +name = "rustls-platform-verifier" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", ] [[package]] -name = "regex-syntax" -version = "0.8.10" +name = "rustls-platform-verifier-android" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] -name = "rsa" -version = "0.9.10" +name = "rustls-webpki" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "signature", - "spki", - "subtle", - "zeroize", + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted 0.9.0", ] [[package]] @@ -1170,12 +3298,65 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.228" @@ -1186,6 +3367,26 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -1203,7 +3404,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", ] [[package]] @@ -1219,6 +3420,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1231,6 +3441,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serdect" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53" +dependencies = [ + "base16ct", + "serde", + "zeroize", +] + [[package]] name = "sha1" version = "0.10.6" @@ -1238,10 +3459,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", ] +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + [[package]] name = "sha2" version = "0.10.9" @@ -1249,10 +3476,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.6" @@ -1268,8 +3501,42 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", - "rand_core", + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "simple_asn1" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror 2.0.18", + "time", ] [[package]] @@ -1340,7 +3607,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener", + "event-listener 5.4.1", "futures-core", "futures-intrusive", "futures-io", @@ -1356,7 +3623,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror", + "thiserror 2.0.18", "tokio", "tokio-stream", "tracing", @@ -1373,7 +3640,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn", + "syn 2.0.108", ] [[package]] @@ -1396,7 +3663,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn", + "syn 2.0.108", "tokio", "url", ] @@ -1413,7 +3680,7 @@ dependencies = [ "byteorder", "bytes", "crc", - "digest", + "digest 0.10.7", "dotenvy", "either", "futures-channel", @@ -1430,7 +3697,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.6", "rsa", "serde", "sha1", @@ -1438,7 +3705,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.18", "tracing", "whoami", ] @@ -1468,14 +3735,14 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.6", "serde", "serde_json", "sha2", "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 2.0.18", "tracing", "whoami", ] @@ -1499,74 +3766,258 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror", + "thiserror 2.0.18", + "tracing", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stack-auth" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c823cc3d88e15478d51694ef56037400bd4ae3e1a9e046071e01d251168cc466" +dependencies = [ + "aquamarine", + "base64", + "cts-common", + "jsonwebtoken", + "miette", + "open", + "reqwest", + "serde", + "serde_json", + "stack-profile", + "thiserror 1.0.69", + "tokio", "tracing", "url", + "uuid", + "vitaminc", + "vitaminc-protected", + "web-time", + "zeroize", + "zerokms-protocol", +] + +[[package]] +name = "stack-profile" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1be30119d59260f3e932f78fbbfbe3674c151d39e7fcca24d0439e7e31ba8" +dependencies = [ + "dirs", + "gethostname", + "serde", + "serde_json", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" +name = "textwrap" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.2.2", +] [[package]] -name = "stringprep" -version = "0.1.5" +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", + "thiserror-impl 1.0.69", ] [[package]] -name = "subtle" -version = "2.6.1" +name = "thiserror" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] [[package]] -name = "syn" -version = "2.0.108" +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn 2.0.108", ] [[package]] -name = "synstructure" -version = "0.13.2" +name = "thiserror-impl" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", ] [[package]] -name = "thiserror" -version = "2.0.17" +name = "time" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ - "thiserror-impl", + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", ] [[package]] -name = "thiserror-impl" -version = "2.0.17" +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ - "proc-macro2", - "quote", - "syn", + "num-conv", + "time-core", ] [[package]] @@ -1619,7 +4070,17 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", ] [[package]] @@ -1633,6 +4094,140 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db3bae107c9522f86d361697dee1d7386a2ddcf659d5aea5159819a21a3c4a7" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "async-compression", + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -1653,7 +4248,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", ] [[package]] @@ -1665,11 +4260,23 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unarray" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" @@ -1689,6 +4296,12 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.24" @@ -1704,6 +4317,52 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.7" @@ -1722,27 +4381,204 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utoipa" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "url", + "uuid", +] + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "atomic", + "getrandom 0.4.2", + "js-sys", + "md-5", + "serde_core", + "sha1_smol", + "wasm-bindgen", +] + [[package]] name = "uuid-simd" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" dependencies = [ - "outref", - "vsimd", + "outref", + "vsimd", +] + +[[package]] +name = "validator" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa" +dependencies = [ + "idna", + "once_cell", + "regex", + "serde", + "serde_derive", + "serde_json", + "url", + "validator_derive", +] + +[[package]] +name = "validator_derive" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca" +dependencies = [ + "darling", + "once_cell", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vitaminc" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9807fc6a29a9ab4a9cd24f103573661d7e04d48651ce8c752d32e73a686446" +dependencies = [ + "vitaminc-aead", + "vitaminc-encrypt", + "vitaminc-protected", + "vitaminc-random", + "vitaminc-traits", +] + +[[package]] +name = "vitaminc-aead" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3933759550ab4841536e8d019fc73cd77ec2e43dcdaefa3218936534eefabb8d" +dependencies = [ + "bytes", + "serde", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vitaminc-encrypt" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdbcfd5e9054ce2a3f0cfac67c3e3164d65f38f3a6d593bc4d5d943e53aaf44" +dependencies = [ + "aes-gcm", + "aws-lc-rs", + "vitaminc-aead", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vitaminc-protected" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c639c70c23871680d0cedabb2fb8cfd0ff91eb98d90dd27e9bdebf6eac1fd18" +dependencies = [ + "bitvec", + "digest 0.11.3", + "serde", + "serde_bytes", + "subtle", + "vitaminc-protected-derive", + "zeroize", +] + +[[package]] +name = "vitaminc-protected-derive" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659afc33e7252768204f44bd9f377a120a35dc586aa3538b66a3f4cc54a88653" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "vitaminc-random" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac67bf5f90acc53c87deb5f612ad1beefd0e0e7f5452ab3443d9fa4b0e23f9c5" +dependencies = [ + "getrandom 0.4.2", + "rand 0.10.1", + "thiserror 2.0.18", + "vitaminc-protected", + "vitaminc-random-derives", + "zeroize", ] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "vitaminc-random-derives" +version = "0.2.0-pre" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "efeeb4347ca86ff167228cfbd655c7a6e8a5bd6f032330ac881d6c4c0441768b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] [[package]] -name = "version_check" -version = "0.9.5" +name = "vitaminc-traits" +version = "0.2.0-pre" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "5aeb6ef24c094d225d00753134f082eba59ea2ba8d5d0b5ba761c038ca9375b3" +dependencies = [ + "anyhow", + "bytes", + "rmp-serde", + "serde", + "thiserror 2.0.18", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] [[package]] name = "vsimd" @@ -1750,6 +4586,25 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1762,7 +4617,16 @@ version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] @@ -1780,10 +4644,21 @@ dependencies = [ "cfg-if", "once_cell", "rustversion", + "serde", "wasm-bindgen-macro", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.121" @@ -1803,7 +4678,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.108", "wasm-bindgen-shared", ] @@ -1816,6 +4691,82 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "whoami" version = "1.6.1" @@ -1826,12 +4777,113 @@ dependencies = [ "wasite", ] +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1841,6 +4893,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -2054,18 +5115,142 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winnow" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.108", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.108", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "yoke" version = "0.8.0" @@ -2086,7 +5271,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", "synstructure", ] @@ -2107,7 +5292,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", ] [[package]] @@ -2127,7 +5312,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", "synstructure", ] @@ -2136,6 +5321,43 @@ name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerokms-protocol" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04a9411f442b247e7d00c6a07cfbc6d56c12d485cfaf4f7effa001bfb1615296" +dependencies = [ + "base64", + "cipherstash-config", + "const-hex", + "cts-common", + "fake", + "getrandom 0.2.16", + "opaque-debug", + "rand 0.8.6", + "serde", + "static_assertions", + "thiserror 1.0.69", + "utoipa", + "uuid", + "validator", + "zeroize", +] [[package]] name = "zerotrie" @@ -2167,5 +5389,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.108", ] diff --git a/tests/sqlx/Cargo.toml b/tests/sqlx/Cargo.toml index 875383cf..12273e6c 100644 --- a/tests/sqlx/Cargo.toml +++ b/tests/sqlx/Cargo.toml @@ -11,6 +11,7 @@ serde_json = "1" anyhow = "1" hex = "0.4" jsonschema = { version = "0.46.4", default-features = false } +cipherstash-client = { version = "0.35", features = ["tokio"] } [dev-dependencies] # None needed - tests live in this crate @@ -22,3 +23,12 @@ default = [] # it on push to main and on a nightly schedule. Run locally with: # mise run test:bench bench = [] +# Opt-in to compiling the fixture generators. Without this feature the +# `#[cfg(feature = "fixture-gen")]` generator tests do not exist, so +# `cargo test` and CI never see them. Generators need a live Postgres and, +# in the process env, BOTH a ZeroKMS auth credential (`CS_CLIENT_ACCESS_KEY` +# + `CS_WORKSPACE_CRN`, via AutoStrategy) AND a client key (`CS_CLIENT_ID` + +# `CS_CLIENT_KEY`, via EnvKeyProvider) — the two pairs are not alternatives. +# Run one with: +# mise run fixture:generate +fixture-gen = [] diff --git a/tests/sqlx/README.md b/tests/sqlx/README.md index ec4e92eb..978ad1f1 100644 --- a/tests/sqlx/README.md +++ b/tests/sqlx/README.md @@ -48,6 +48,24 @@ cargo test equality cargo test -- --nocapture ``` +### Generator credentials + +`mise run test:sqlx` regenerates the `eql_v2_int4` fixture before running the +suite via `mise run fixture:generate eql_v2_int4`. The generator encrypts +plaintexts in-process using `cipherstash-client` (no Proxy / no Docker +sidecar), so the following CipherStash workspace credentials must be +present in the shell environment when you run it locally or in CI: + +- `CS_CLIENT_ACCESS_KEY` + `CS_WORKSPACE_CRN` — preferred, single-token + bearer credential, picked up by `AutoStrategy::detect()`. +- `CS_CLIENT_ID` + `CS_CLIENT_KEY` — the client-key pair used by + `EnvKeyProvider` to derive the per-call data keys. + +If either set is missing the first call into the generator fails fast +during ZeroKMS handshake with a clear `anyhow` chain naming the missing +variable. Other SQLx tests do not need the `CS_*` variables — only the +fixture-regeneration step does. + ## Test Data ### Fixtures @@ -70,7 +88,7 @@ cargo test -- --nocapture **encryptindex_tables.sql**: Tables for encryption workflow tests - Table: `users` with plaintext columns for encryption testing -**like_data.sql**: Test data for LIKE operator tests +**match_data.sql**: Test data for LIKE operator tests - 3 encrypted records with bloom filter indexes diff --git a/tests/sqlx/fixtures/FIXTURE_SCHEMA.md b/tests/sqlx/fixtures/FIXTURE_SCHEMA.md index 8814dff0..58ecd742 100644 --- a/tests/sqlx/fixtures/FIXTURE_SCHEMA.md +++ b/tests/sqlx/fixtures/FIXTURE_SCHEMA.md @@ -7,13 +7,21 @@ This document defines the structure and dependencies of test fixtures used in th ``` EQL Extension (via migrations) ├── encrypted_json.sql - ├── array_data.sql + │ └── array_data.sql (extends `encrypted` table from encrypted_json) + ├── match_data.sql + ├── aggregate_minmax_data.sql + ├── config_tables.sql + ├── constraint_tables.sql + ├── encryptindex_tables.sql + ├── drop_operator_classes.sql (Supabase-simulation; drops opclasses + ORE operators) ├── order_by_null_data.sql (depends on ore migration) ├── ore table (migration 002 — not a fixture) └── bench_data.sql + bench_setup.sql (depend on migration 007) + +eql_v2_int4.sql (no EQL dependency — generated, plain jsonb, not committed) ``` -All fixtures depend on the EQL extension being installed via SQLx migrations. +All fixtures except the generated `eql_v2_int4.sql` depend on the EQL extension being installed via SQLx migrations. --- @@ -182,6 +190,59 @@ CREATE TABLE bench ( --- +## eql_v2_int4.sql + +**Purpose:** 14 encrypted integers for verifying encrypted-integer fixture +structure. Unlike its neighbours, this is a **generated** fixture — produced by +`mise run fixture:generate eql_v2_int4` (the Rust fixture framework in +`tests/sqlx/src/fixtures/`) and **not committed** (see `.gitignore`). It is +plain SQL with **no EQL dependency**: `payload` is `jsonb`, so the script +applies standalone. + +**Regenerated every test run.** `mise run test:sqlx` invokes the generator +before `cargo test`, so a stale committed fixture cannot mask a payload-shape +regression. The generator encrypts in-process via `cipherstash-client`; it +needs a live Postgres plus **both** CipherStash credential pairs in the shell +environment (they are not alternatives): `CS_CLIENT_ACCESS_KEY` + +`CS_WORKSPACE_CRN` for ZeroKMS auth (AutoStrategy) **and** `CS_CLIENT_ID` + +`CS_CLIENT_KEY` for the client key (EnvKeyProvider). Do not hand-edit the +generated file; it is overwritten in place on every run. + +**Schema:** Table lives in the dedicated `fixtures` SQL schema (kept out of the +`public` type/domain namespace so a downstream `public.eql_v2_int4` domain can +coexist): +```sql +CREATE SCHEMA IF NOT EXISTS fixtures; +CREATE TABLE fixtures.eql_v2_int4 ( + id BIGINT PRIMARY KEY, + plaintext integer NOT NULL, + payload jsonb NOT NULL +); +``` + +**Data:** +- 14 rows, ids 1-14; `id = N` is the Nth generated value. +- `plaintext` values: `-100, -1, 1, 2, 5, 10, 17, 25, 42, 50, 100, 250, 1000, 9999` + — a negative boundary plus small/medium/large/extreme magnitudes. +- `plaintext` is the **in-table oracle**: consuming tests filter + `WHERE plaintext = N` directly, so no Rust value constant is shared. +- Each `payload` is a cipherstash-client-encrypted JSONB object carrying + `c` (ciphertext), `hm` (HMAC equality term), `ob` (ORE block ordering + term), an inert `i` metadata object, and the EQL v2 root discriminator + (`k = "ct"`, `v = 2`). + +**Used By:** +- eql_v2_int4_fixture_tests.rs (structural verification) +- (#225) the `eql_v2_int4` domain operator tests, via per-query `payload` casts + +**Opt-in:** Not a migration — a SQLx fixture script. Each consuming test opts +in explicitly: +```rust +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +``` + +--- + ## Validation Tests Each fixture should have a validation test to ensure correct structure: diff --git a/tests/sqlx/fixtures/like_data.sql b/tests/sqlx/fixtures/match_data.sql similarity index 97% rename from tests/sqlx/fixtures/like_data.sql rename to tests/sqlx/fixtures/match_data.sql index 8f5b2adc..bd7a49c5 100644 --- a/tests/sqlx/fixtures/like_data.sql +++ b/tests/sqlx/fixtures/match_data.sql @@ -1,4 +1,4 @@ --- Fixture: like_data.sql +-- Fixture: match_data.sql -- -- Creates test data for LIKE operator tests (~~ and ~~* operators) -- Tests encrypted-to-encrypted matching using bloom filter indexes diff --git a/tests/sqlx/src/fixtures/cipherstash.rs b/tests/sqlx/src/fixtures/cipherstash.rs new file mode 100644 index 00000000..bb3a69bc --- /dev/null +++ b/tests/sqlx/src/fixtures/cipherstash.rs @@ -0,0 +1,452 @@ +//! Direct `cipherstash-client` integration — the encryption oracle for the +//! SQLx fixture generator. +//! +//! Earlier revisions of the generator started a CipherStash Proxy container, +//! wrote `add_search_config` rows so Proxy knew which columns to encrypt, +//! restarted the container so it reloaded that config, then INSERTed +//! plaintexts through a Proxy-mediated Postgres connection. That whole loop +//! existed only because the Proxy was the encryption oracle. +//! +//! `cipherstash-client` 0.35 exposes the same surface natively. This module +//! owns the bootstrap — `cipher()` lazily builds a process-wide +//! `ScopedCipher` — and the per-value helper +//! `encrypt_store()` that wraps `eql::encrypt_eql` and returns the resulting +//! EQL ciphertext as a `serde_json::Value` ready to bind into a `jsonb` +//! column. +//! +//! `column_config_for` is the bridge between the fixture spec's string-typed +//! index names (`"unique"`, `"ore"`, …) and the typed `IndexType` enum +//! cipherstash-config uses. Unknown names raise immediately so a typo at +//! spec construction fails fast. + +use std::borrow::Cow; +use std::sync::Arc; + +use anyhow::{anyhow, Context, Result}; +use cipherstash_client::encryption::ScopedCipher; +use cipherstash_client::eql::{ + encrypt_eql, EqlCiphertext, EqlEncryptOpts, EqlOperation, EqlOutput, Identifier, + PreparedPlaintext, +}; +use cipherstash_client::schema::column::{Index, IndexType}; +use cipherstash_client::schema::{ColumnConfig, ColumnType}; +use cipherstash_client::zerokms::{EnvKeyProvider, ZeroKMSBuilder}; +use cipherstash_client::AutoStrategy; +use tokio::sync::OnceCell; + +use super::eql_plaintext::{Cast, EqlPlaintext}; +use super::validation::FixtureIdentifier; + +/// Process-wide `ScopedCipher`. Built on first use and held for the lifetime +/// of the test binary — `ScopedCipher` is documented as +/// "initialise once per process, hold an `Arc` for the process lifetime" +/// (see the upstream doc comment in `scoped_cipher.rs`). Re-initialising it +/// per call discards the warm reqwest pool and the cached auth token, and +/// makes the generator slower for no benefit. +static CIPHER: OnceCell>> = OnceCell::const_new(); + +/// Lazily initialise the process-wide cipher. On the first call this performs +/// the AutoStrategy detection, the ZeroKMS handshake, and the keyset load — +/// each subsequent call is an `Arc` clone. +/// +/// Errors surface as `anyhow::Error` with `.context(...)` naming the step +/// that failed (credential detection vs ZeroKMS connect vs keyset load). +pub async fn cipher() -> Result>> { + CIPHER + .get_or_try_init(|| async { + let zerokms = ZeroKMSBuilder::auto() + .context( + "building ZeroKMSBuilder via AutoStrategy::detect() — check \ + CS_CLIENT_ACCESS_KEY or CS_WORKSPACE_CRN env vars", + )? + .with_key_provider(EnvKeyProvider) + .build() + .await + .context( + "building ZeroKMS client — check CS_CLIENT_ID + CS_CLIENT_KEY \ + env vars (loaded by EnvKeyProvider)", + )?; + + let cipher = ScopedCipher::init_default(Arc::new(zerokms)) + .await + .context("initialising ScopedCipher for the default keyset")?; + + Ok::<_, anyhow::Error>(Arc::new(cipher)) + }) + .await + .cloned() +} + +/// Build a `ColumnConfig` from the fixture spec's index list + cast. +/// +/// The fixture spec uses EQL's string-typed index identifiers (`"unique"`, +/// `"ore"`, `"match"`, `"ste_vec"`); cipherstash-config uses the typed +/// `IndexType` enum. The mapping here is the single point of contact +/// between the two — extending fixture coverage to a new index means one +/// new arm here plus the corresponding `EqlPlaintext::CAST` constant. +/// +/// Unknown identifiers raise immediately with the offending name in the +/// error so a typo at spec-construction surfaces at run time (the +/// `FixtureIdentifier` newtype only proves the string is a valid SQL +/// identifier, not that it names a real index type). +pub fn column_config_for(spec_indexes: &[FixtureIdentifier], cast: Cast) -> Result { + let column_type = cast_to_column_type(cast)?; + let mut config = ColumnConfig::build("payload").casts_as(column_type); + + for ix in spec_indexes { + let index_type = index_type_for(ix.as_str())?; + config = config.add_index(Index::new(index_type)); + } + + Ok(config) +} + +/// Map an `EqlPlaintext::Cast` onto cipherstash-config's `ColumnType`. The +/// `Cast` newtype's allowlist is structural, so the only failure mode is +/// "we extended `EqlPlaintext` with a new variant but forgot to extend +/// this mapping" — explicit error rather than a `_ => unreachable!()` +/// gives the maintainer a clear breadcrumb. +fn cast_to_column_type(cast: Cast) -> Result { + match cast.as_str() { + "int" => Ok(ColumnType::Int), + "small_int" => Ok(ColumnType::SmallInt), + "big_int" => Ok(ColumnType::BigInt), + "boolean" => Ok(ColumnType::Boolean), + "date" => Ok(ColumnType::Date), + "decimal" => Ok(ColumnType::Decimal), + "float" | "real" | "double" => Ok(ColumnType::Float), + "text" => Ok(ColumnType::Text), + "jsonb" | "json" => Ok(ColumnType::Json), + "timestamp" => Ok(ColumnType::Timestamp), + other => Err(anyhow!( + "no cipherstash-config ColumnType mapping for cast {other:?} — \ + extend cipherstash::cast_to_column_type when adding a new \ + EqlPlaintext variant" + )), + } +} + +/// Map the fixture spec's string-typed index identifier onto a typed +/// `IndexType`. Reuses the canonical constructors on `Index` +/// (`Index::new_unique`, etc.) so the defaults stay in sync with whatever +/// cipherstash-config considers the canonical shape for each index. +fn index_type_for(name: &str) -> Result { + match name { + "unique" => Ok(Index::new_unique().index_type), + "ore" => Ok(IndexType::Ore), + "match" => Ok(Index::new_match().index_type), + other => Err(anyhow!( + "unknown EQL index identifier {other:?} — supported: \ + unique, ore, match" + )), + } +} + +/// Encrypt a batch of plaintext values for storage and return one EQL +/// ciphertext per input as a `serde_json::Value` ready to bind into a +/// `jsonb` column. +/// +/// One `encrypt_eql` call regardless of `values.len()` — ZeroKMS does the +/// round trip once, not N times. The per-value field in each +/// `PreparedPlaintext` is `value.to_plaintext()`; the config, identifier, +/// and `EqlOperation::Store` are shared across the batch. +/// +/// Uses `EqlOperation::Store`, which yields a full storage payload +/// (`{"k": "ct", "v": 2, "i": …, "c": …, "hm": …, "ob": …}`) — the same +/// shape Proxy produced for the working table. `EqlEncryptOpts::default()` +/// uses the cipher's default keyset, no lock context, no service token, no +/// index filter — the same defaults Proxy uses for column-config-driven +/// inserts. +/// +/// An empty `values` slice short-circuits before `cipher()` so a caller +/// with nothing to encrypt does not pay the ZeroKMS bootstrap cost. +pub async fn encrypt_store( + table: &str, + column: &str, + values: &[T], + config: &ColumnConfig, +) -> Result> { + if values.is_empty() { + return Ok(Vec::new()); + } + + let cipher = cipher().await?; + + // `Identifier::new` does two `String` allocations per call — cheap + // enough that constructing per-iteration is preferred over assuming + // the upstream type implements `Clone`. + let prepared: Vec = values + .iter() + .map(|value| { + PreparedPlaintext::new( + Cow::Borrowed(config), + Identifier::new(table, column), + value.to_plaintext(), + EqlOperation::Store, + ) + }) + .collect(); + + let opts = EqlEncryptOpts::default(); + let outputs = encrypt_eql(cipher, prepared, &opts) + .await + .with_context(|| { + format!( + "encrypting batch of {} values for {table}.{column}", + values.len() + ) + })?; + + if outputs.len() != values.len() { + return Err(anyhow!( + "encrypt_eql returned {} outputs for {} inputs", + outputs.len(), + values.len() + )); + } + + outputs + .into_iter() + .map(|output| { + let ciphertext: EqlCiphertext = match output { + EqlOutput::Store(ct) => ct, + EqlOutput::Query(_) => { + // EqlOperation::Store always yields EqlOutput::Store; + // treating the other arm as unreachable would hide a + // future API drift. + return Err(anyhow!( + "encrypt_eql returned a Query output for an EqlOperation::Store input" + )); + } + }; + serde_json::to_value(&ciphertext).context("serialising EqlCiphertext to JSON") + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + fn ident(s: &str) -> FixtureIdentifier { + FixtureIdentifier::try_from(s).unwrap() + } + + #[test] + fn column_config_for_int_with_unique_and_ore_builds_a_two_index_config() { + let indexes = [ident("unique"), ident("ore")]; + let config = column_config_for(&indexes, Cast::INT).unwrap(); + + assert_eq!(config.name, "payload"); + assert!(matches!(config.cast_type, ColumnType::Int)); + assert_eq!(config.indexes.len(), 2); + assert!(config.indexes.iter().any(|i| i.is_unique())); + assert!(config.indexes.iter().any(|i| i.is_ore())); + } + + #[test] + fn column_config_for_rejects_an_unknown_index_name() { + let indexes = [ident("bogus")]; + let err = column_config_for(&indexes, Cast::INT).unwrap_err(); + assert!( + format!("{err:#}").contains("unknown EQL index identifier"), + "error should name the unknown identifier: {err:#}" + ); + } + + #[test] + fn index_type_for_maps_known_names_to_their_canonical_index_type() { + // The named EQL index identifiers each round-trip into the + // `IndexType` cipherstash-config considers canonical for that + // name. Compared via the public `Index` surface (`is_unique`, + // `is_ore`, `is_match`) so the assertion does not depend on the + // shape of the non-exhaustive `IndexType` enum. + let unique = Index::new(index_type_for("unique").unwrap()); + assert!(unique.is_unique(), "'unique' must map to the unique index"); + + let ore = Index::new(index_type_for("ore").unwrap()); + assert!(ore.is_ore(), "'ore' must map to the ORE index"); + + let m = Index::new(index_type_for("match").unwrap()); + assert!(m.is_match(), "'match' must map to the match (bloom) index"); + } + + #[test] + fn index_type_for_rejects_an_unknown_index_name() { + let err = index_type_for("bogus").unwrap_err(); + let msg = format!("{err:#}"); + assert!( + msg.contains("unknown EQL index identifier") && msg.contains("bogus"), + "error should name the offending identifier: {msg}" + ); + } + + #[tokio::test] + async fn encrypt_store_with_empty_values_returns_an_empty_vec_without_calling_cipher() { + // Empty input short-circuits before `cipher()` so a caller with + // nothing to encrypt does not pay the ZeroKMS bootstrap cost. + // Running this test under `cargo test` (no `fixture-gen` feature, + // no CS_* env vars) proves the short-circuit: if `cipher()` were + // reached, the missing credentials would surface as an error. + let config = column_config_for(&[ident("unique")], Cast::INT).unwrap(); + let out = encrypt_store::("t", "c", &[], &config).await.unwrap(); + assert!(out.is_empty(), "empty input must yield empty output"); + } + + #[test] + fn cast_to_column_type_covers_every_eql_plaintext_cast_constant() { + // Every Cast constant on EqlPlaintext must round-trip into a + // ColumnType — otherwise a freshly-added EqlPlaintext variant + // would crash the generator at run time instead of failing the + // build. Listed explicitly so a new `pub const` on Cast forces an + // update here. + for cast in [ + Cast::TEXT, + Cast::INT, + Cast::SMALL_INT, + Cast::BIG_INT, + Cast::REAL, + Cast::DOUBLE, + Cast::BOOLEAN, + Cast::DATE, + Cast::JSONB, + Cast::JSON, + Cast::FLOAT, + Cast::DECIMAL, + Cast::TIMESTAMP, + ] { + cast_to_column_type(cast).unwrap_or_else(|e| { + panic!("Cast::{} has no ColumnType mapping: {e}", cast.as_str()) + }); + } + } +} + +/// Live `encrypt_store` round-trips against a real ZeroKMS keyset. Gated +/// by `fixture-gen` so default `cargo test` runs do not require +/// `CS_CLIENT_ACCESS_KEY` / `CS_WORKSPACE_CRN`. Each test is +/// `#[ignore]` so it only runs under +/// `cargo test --features fixture-gen -- --ignored --test-threads=1`, +/// mirroring the `generate` test in `eql_v2_int4.rs`. +/// +/// **Must run serially (`--test-threads=1`).** The process-wide +/// `CIPHER` `OnceCell` caches a `ScopedCipher` whose reqwest connection +/// pool is bound to the tokio runtime that initialised it. Each +/// `#[tokio::test]` builds its own runtime, so under parallel +/// execution the second test's calls go through a pool whose +/// dispatcher has been dropped — failing with +/// "SendRequest: dispatch task is gone". Production fixture runs (one +/// `#[tokio::main]` runtime) are unaffected. +/// +/// These complement the structural fixture-tests in +/// `tests/sqlx/tests/eql_v2_int4_fixture_tests.rs`: those assert over the +/// regenerated SQL file end-to-end; these isolate the +/// `encrypt_store` call so an SDK API drift surfaces here before the +/// whole fixture pipeline fails. +#[cfg(all(test, feature = "fixture-gen"))] +mod live_tests { + use super::*; + use serde_json::Value; + + fn ident(s: &str) -> FixtureIdentifier { + FixtureIdentifier::try_from(s).unwrap() + } + + /// Config used by every live test — `unique` drives the `hm` term, + /// `ore` drives the `ob` term, so the returned payloads carry both. + fn int_config_with_hm_and_ob() -> ColumnConfig { + column_config_for(&[ident("unique"), ident("ore")], Cast::INT).unwrap() + } + + /// Assert the well-formed Store shape: the payload is a JSON object + /// with non-null `v`, `c`, `hm`, `ob`, and `i` fields. Mirrors the + /// per-key assertions in `eql_v2_int4_fixture_tests.rs`. + fn assert_store_shape(payload: &Value) { + let obj = payload.as_object().expect("payload must be a JSON object"); + for key in ["v", "c", "hm", "ob", "i"] { + assert!( + obj.get(key).is_some_and(|v| !v.is_null()), + "payload must carry a non-null `{key}` field; got {payload}" + ); + } + // `v` is the EQL payload-format version. The cipherstash-client + // JSON encodes it as the integer 2; the existing fixture tests + // check `payload->>'v' = '2'` via Postgres's text-cast operator. + // Asserting the number here matches the source format directly. + assert_eq!( + obj.get("v").and_then(Value::as_i64), + Some(2), + "payload must declare v = 2; got {payload}" + ); + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_single_value_returns_one_eql_payload() { + let config = int_config_with_hm_and_ob(); + let out = encrypt_store("live_one", "payload", &[42_i32], &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + assert_eq!(out.len(), 1, "single input should produce single output"); + assert_store_shape(&out[0]); + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_batch_returns_one_payload_per_input_in_input_order() { + let config = int_config_with_hm_and_ob(); + let values = [-1_i32, 1, 42]; + let out = encrypt_store("live_batch", "payload", &values, &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + assert_eq!( + out.len(), + values.len(), + "batch length must equal input length" + ); + for (i, payload) in out.iter().enumerate() { + assert_store_shape(payload); + // Each payload's `i.t` should match the table identifier we + // supplied — that's the field consuming code uses to bind a + // payload to its source column. + let identifier_t = payload + .get("i") + .and_then(Value::as_object) + .and_then(|o| o.get("t")) + .and_then(Value::as_str); + assert_eq!( + identifier_t, + Some("live_batch"), + "payload[{i}].i.t must match the table argument; got {payload}" + ); + } + } + + #[tokio::test] + #[ignore = "live ZeroKMS — run via `cargo test --features fixture-gen -- --ignored`"] + async fn encrypt_store_batch_distinct_plaintexts_yield_distinct_hm() { + // HMAC is the equality term — three distinct plaintexts must + // yield three distinct `hm` strings. Mirrors + // `hmac_equality_terms_are_distinct_for_distinct_values` in the + // fixture-tests but at the unit-test layer. + let config = int_config_with_hm_and_ob(); + let out = encrypt_store("live_distinct", "payload", &[-1_i32, 1, 42], &config) + .await + .expect("encrypt_store should succeed against live ZeroKMS"); + + let hms: Vec<&str> = out + .iter() + .map(|p| { + p.get("hm") + .and_then(Value::as_str) + .expect("payload must carry a string `hm` term") + }) + .collect(); + let unique: std::collections::HashSet<&&str> = hms.iter().collect(); + assert_eq!( + unique.len(), + hms.len(), + "distinct plaintexts must yield distinct hm terms; got {hms:?}" + ); + } +} diff --git a/tests/sqlx/src/fixtures/driver.rs b/tests/sqlx/src/fixtures/driver.rs new file mode 100644 index 00000000..90060a5f --- /dev/null +++ b/tests/sqlx/src/fixtures/driver.rs @@ -0,0 +1,373 @@ +//! `FixtureSpec::run()` — the generation driver. +//! +//! mise owns the containers; this owns the data. The driver opens a direct +//! Postgres connection and encrypts each plaintext value via +//! `cipherstash-client` (see the sibling `cipherstash` module) before +//! inserting the result into a transient working table. Errors are `anyhow` +//! with `.context(...)` — a generator is a developer tool; a clear crash +//! beats a partial fixture. +//! +//! The `public._fixture_` working table is transient plumbing: `.run()` +//! creates it, encrypts into it, renders the committed rows from it, then +//! drops it before returning. The drop runs unconditionally once the table +//! exists — on success *and* on any returned error: `run` captures the +//! post-schema result, drops the table, and only then propagates a failure. +//! So the table never outlives a *returned* run; only a hard crash (panic / +//! `kill`) can leak it, and the next run's start-of-schema +//! `DROP TABLE IF EXISTS` reclaims that case. + +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use sqlx::postgres::PgConnectOptions; +use sqlx::{ConnectOptions, Connection, PgConnection, Row}; + +use super::cipherstash; +use super::eql_plaintext::EqlPlaintext; +use super::spec::FixtureSpec; + +/// Bag of Rust-type bounds required of a fixture's plaintext value `T`. +/// Collapses the long `where` clause on `impl FixtureSpec<'a, T>` to a single +/// alias; the blanket impl below makes it auto-applied to any `T` that +/// already satisfies the bounds. +pub trait FixtureValue: + EqlPlaintext + + Copy + + Send + + Sync + + for<'q> sqlx::Encode<'q, sqlx::Postgres> + + sqlx::Type +{ +} + +impl FixtureValue for T where + T: EqlPlaintext + + Copy + + Send + + Sync + + for<'q> sqlx::Encode<'q, sqlx::Postgres> + + sqlx::Type +{ +} + +/// Driver connection options, parsed once from the environment at the start +/// of `run`. Only the unmediated Postgres connection is needed: DDL, +/// inserts, and the render step all run against it. Encryption happens in +/// Rust (cipherstash-client), so there is no second connection. +struct DriverConfig { + direct: PgConnectOptions, +} + +impl DriverConfig { + /// Build connection options from env vars, defaulting to the + /// `mise.toml` `[env]` values. Port parses are strict — a malformed + /// `POSTGRES_PORT` surfaces as an `anyhow::Error` with the offending + /// value, matching the rest of the driver's error story. + fn from_env() -> Result { + let host = env_or("POSTGRES_HOST", "localhost"); + let user = env_or("POSTGRES_USER", "cipherstash"); + let password = env_or("POSTGRES_PASSWORD", "password"); + let database = env_or("POSTGRES_DB", "cipherstash"); + let port = parse_port_env("POSTGRES_PORT", 7432)?; + + let direct = PgConnectOptions::new() + .host(&host) + .port(port) + .username(&user) + .password(&password) + .database(&database); + + Ok(Self { direct }) + } +} + +fn env_or(key: &str, default: &str) -> String { + std::env::var(key).unwrap_or_else(|_| default.to_string()) +} + +fn parse_port_env(key: &str, default: u16) -> Result { + match std::env::var(key) { + Ok(value) => value + .parse::() + .with_context(|| format!("{key}={value:?} must be a valid u16")), + Err(_) => Ok(default), + } +} + +/// Absolute path to `tests/sqlx/fixtures/.sql`. Resolved from +/// `CARGO_MANIFEST_DIR` (the `tests/sqlx` crate root) so the path is correct +/// regardless of the process working directory. +fn fixture_script_path(filename: &str) -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("fixtures") + .join(filename) +} + +impl<'a, T> FixtureSpec<'a, T> +where + T: FixtureValue, +{ + /// Generate and write `tests/sqlx/fixtures/.sql`. + /// + /// The production entry point. Parses the env-driven `DriverConfig` + /// once, opens a direct Postgres connection, then delegates the + /// schema + teardown orchestration to `run_with`, supplying + /// `insert_direct` as the closure. After `run_with` returns the + /// rendered INSERT lines, this method composes them with + /// `fixture_script_preamble` and writes the committed script to disk. + pub async fn run(&self) -> Result<()> { + let config = DriverConfig::from_env()?; + + let mut direct = config + .direct + .clone() + .connect() + .await + .context("connecting to Postgres (direct)")?; + + // Second direct connection for the inserter closure. `run_with` + // borrows the first connection mutably for the duration of the + // pipeline, so the inserter must hold its own. + let mut inserter_conn = config + .direct + .clone() + .connect() + .await + .context("connecting to Postgres (direct inserter)")?; + + let lines = self + .run_with(&mut direct, || self.insert_direct(&mut inserter_conn)) + .await?; + + let _ = inserter_conn.close().await; + let _ = direct.close().await; + + let mut script = self.fixture_script_preamble(); + for line in &lines { + script.push_str(line); + script.push('\n'); + } + + let path = fixture_script_path(&self.script_filename()); + std::fs::write(&path, script) + .with_context(|| format!("writing fixture script {}", path.display()))?; + println!("wrote {} ({} rows)", path.display(), self.values().len()); + Ok(()) + } + + /// Encrypt every plaintext value via cipherstash-client in **one + /// batched call**, then INSERT each ciphertext into the working + /// table as plain JSONB. The committed `ColumnConfig` is built once + /// from the spec's indexes + cast — the fixture name is fed as the + /// table identifier so the resulting payload's `i.t` field matches + /// the working table, preserving the shape Proxy used to emit. + /// + /// Batching means one ZeroKMS round trip per fixture run regardless + /// of value count; the INSERT loop is per-row because the working + /// table is local Postgres and the per-row execute cost is in + /// microseconds. + async fn insert_direct(&self, direct: &mut PgConnection) -> Result<()> { + let config = cipherstash::column_config_for(self.indexes(), T::CAST) + .context("building ColumnConfig from FixtureSpec indexes")?; + + let working = self.working_table(); + let payloads = cipherstash::encrypt_store(&working, "payload", self.values(), &config) + .await + .context("encrypting fixture values")?; + + let insert = + format!("INSERT INTO public.{working} (id, plaintext, payload) VALUES ($1, $2, $3)"); + for (i, (value, payload)) in self.values().iter().zip(payloads).enumerate() { + let id = (i as i64) + 1; + sqlx::query(&insert) + .bind(id) + .bind(*value) + .bind(sqlx::types::Json(payload)) + .execute(&mut *direct) + .await + .with_context(|| format!("inserting value #{id}"))?; + } + Ok(()) + } + + /// Orchestrates the schema-apply / insert / render / teardown pipeline + /// against a caller-supplied `direct` connection, with the insert step + /// pluggable via `insert_rows`. The pipeline is: + /// + /// 1. Check the spec is complete. + /// 2. Apply `working_schema_sql` on `direct`. After this succeeds the + /// `public._fixture_` table exists and MUST be dropped before + /// return, whatever happens next. + /// 3. Run `insert_rows()`. Its result is captured (not `?`-propagated) + /// so the drop in step 5 always runs. + /// 4. If the inserter succeeded, render the committed rows via + /// `render_rows_sql` on `direct`. Skipped on inserter error. + /// 5. Drop the working table on `direct` unconditionally. + /// 6. Propagate failures in causal order: inserter error first + /// (root cause), then render, then drop. + /// + /// `run()` calls this with `insert_direct`. Tests call it with + /// closures that insert hand-crafted JSONB payloads directly (no + /// cipherstash-client required), or with closures that return `Err` + /// to exercise the teardown contract. + /// + /// Private by design: this is a test seam, not a public API. Other + /// fixtures must go through `run`. + async fn run_with( + &self, + direct: &mut PgConnection, + insert_rows: F, + ) -> Result> + where + F: FnOnce() -> Fut + Send, + Fut: std::future::Future> + Send, + { + self.check_complete().context("invalid FixtureSpec")?; + + sqlx::raw_sql(&self.working_schema_sql()) + .execute(&mut *direct) + .await + .context("applying working-table schema")?; + + let insert_result = insert_rows().await; + let render_result = if insert_result.is_ok() { + sqlx::query(&self.render_rows_sql()) + .fetch_all(&mut *direct) + .await + .context("rendering fixture rows") + } else { + // Empty placeholder — never observed; `insert_result?` below short-circuits. + Ok(Vec::new()) + }; + + let working = self.working_table(); + let drop_result = sqlx::raw_sql(&format!("DROP TABLE IF EXISTS public.{working};")) + .execute(&mut *direct) + .await; + + insert_result?; + let rows = render_result?; + drop_result.context("dropping the working table")?; + + rows.iter() + .map(|r| r.try_get::(0).context("reading rendered INSERT")) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sqlx::PgPool; + + /// A small int4 spec for driver tests. Three values keeps the test fast; + /// the driver's orchestration is independent of value count. + fn small_spec(name: &'static str) -> FixtureSpec<'static, i32> { + const VALUES: &[i32] = &[-1, 1, 42]; + FixtureSpec::new(name) + .with_index("unique") + .with_index("ore") + .with_column_type("jsonb") + .with_values(VALUES) + } + + #[sqlx::test] + async fn run_with_renders_committed_rows_and_drops_working_table(pool: PgPool) -> Result<()> { + let spec = small_spec("driver_test_a"); + let working = spec.working_table(); + let working_for_closure = working.clone(); + let pool_for_closure = pool.clone(); + + let mut conn = pool.acquire().await?; + + let lines = spec + .run_with(&mut *conn, move || async move { + // Working table should exist while the closure runs. + let mut c = pool_for_closure.acquire().await?; + let exists: Option = sqlx::query_scalar(&format!( + "SELECT to_regclass('public.{working_for_closure}')::text" + )) + .fetch_one(&mut *c) + .await?; + assert!( + exists.is_some(), + "working table should exist inside the closure" + ); + + for (i, value) in [-1i32, 1, 42].iter().enumerate() { + let id = (i as i64) + 1; + let insert = format!( + "INSERT INTO public.{working_for_closure} \ + (id, plaintext, payload) \ + VALUES ($1, $2, $3::jsonb)" + ); + sqlx::query(&insert) + .bind(id) + .bind(*value) + .bind( + r#"{"v":2,"c":"x","i":{"t":"_fixture_driver_test_a","c":"payload"},"hm":"x","ob":["1"]}"#, + ) + .execute(&mut *c) + .await?; + } + Ok(()) + }) + .await?; + + assert_eq!(lines.len(), 3, "one rendered INSERT per inserted row"); + for line in &lines { + assert!( + line.starts_with( + "INSERT INTO fixtures.driver_test_a (id, plaintext, payload) VALUES (" + ), + "rendered line should target the committed table: {line}" + ); + } + + let after: Option = + sqlx::query_scalar(&format!("SELECT to_regclass('public.{working}')::text")) + .fetch_one(&pool) + .await?; + assert!( + after.is_none(), + "working table should be dropped after run_with returns" + ); + + Ok(()) + } + + #[sqlx::test] + async fn run_with_drops_working_table_on_inserter_error(pool: PgPool) -> Result<()> { + let spec = small_spec("driver_test_b"); + let working = spec.working_table(); + + let mut conn = pool.acquire().await?; + + let result = spec + .run_with(&mut *conn, || async { + anyhow::bail!("forced failure for test") + }) + .await; + + assert!( + result.is_err(), + "run_with should propagate the inserter error" + ); + let err_msg = format!("{:#}", result.unwrap_err()); + assert!( + err_msg.contains("forced failure for test"), + "error chain should contain the forced failure: {err_msg}" + ); + + let after: Option = + sqlx::query_scalar(&format!("SELECT to_regclass('public.{working}')::text")) + .fetch_one(&pool) + .await?; + assert!( + after.is_none(), + "working table should be dropped even on inserter error" + ); + + Ok(()) + } +} diff --git a/tests/sqlx/src/fixtures/eql_plaintext.rs b/tests/sqlx/src/fixtures/eql_plaintext.rs new file mode 100644 index 00000000..4cdc807d --- /dev/null +++ b/tests/sqlx/src/fixtures/eql_plaintext.rs @@ -0,0 +1,122 @@ +//! Maps a Rust plaintext type `T` to its EQL search-config cast and the SQL +//! type of the `plaintext` column. +//! +//! `Cast` and `PlaintextSqlType` are newtypes with private fields; the only +//! way to obtain one is via the predeclared constants on each type. That +//! makes the EQL allowlist structural — a `T::CAST` is, by construction, a +//! value EQL accepts. The trait is sealed so external crates cannot add +//! impls that bypass this guarantee. +//! +//! `to_plaintext` lifts the value into the cipherstash-client +//! `encryption::Plaintext` enum so the fixture generator can encrypt directly +//! via `eql::encrypt_eql` (no Proxy round trip). + +use std::fmt; + +use cipherstash_client::encryption::Plaintext; + +/// The `cast_as` argument for `eql_v2.add_search_config`. The field is +/// private so the allowlist is the set of `pub const`s below. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Cast(&'static str); + +impl Cast { + pub const TEXT: Cast = Cast("text"); + pub const INT: Cast = Cast("int"); + pub const SMALL_INT: Cast = Cast("small_int"); + pub const BIG_INT: Cast = Cast("big_int"); + pub const REAL: Cast = Cast("real"); + pub const DOUBLE: Cast = Cast("double"); + pub const BOOLEAN: Cast = Cast("boolean"); + pub const DATE: Cast = Cast("date"); + pub const JSONB: Cast = Cast("jsonb"); + pub const JSON: Cast = Cast("json"); + pub const FLOAT: Cast = Cast("float"); + pub const DECIMAL: Cast = Cast("decimal"); + pub const TIMESTAMP: Cast = Cast("timestamp"); + + pub fn as_str(&self) -> &'static str { + self.0 + } +} + +impl fmt::Display for Cast { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +/// The SQL type for the `plaintext` oracle column. As with `Cast`, the only +/// way to construct one is via the predeclared constants below. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct PlaintextSqlType(&'static str); + +impl PlaintextSqlType { + pub const INTEGER: PlaintextSqlType = PlaintextSqlType("integer"); + + pub fn as_str(&self) -> &'static str { + self.0 + } +} + +impl fmt::Display for PlaintextSqlType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for i32 {} +} + +/// A Rust type usable as a fixture `plaintext` value, carrying its EQL cast +/// and the SQL type of the `plaintext` column. Sealed; only this crate may +/// add impls. +pub trait EqlPlaintext: sealed::Sealed { + const CAST: Cast; + const PLAINTEXT_SQL_TYPE: PlaintextSqlType; + + /// Lift the Rust value into the cipherstash-client `Plaintext` enum the + /// EQL encryption pipeline consumes. The mapping is total — every + /// `EqlPlaintext` impl maps cleanly onto a `Plaintext::*(Some(_))` + /// variant. + fn to_plaintext(self) -> Plaintext; +} + +impl EqlPlaintext for i32 { + const CAST: Cast = Cast::INT; + const PLAINTEXT_SQL_TYPE: PlaintextSqlType = PlaintextSqlType::INTEGER; + + fn to_plaintext(self) -> Plaintext { + Plaintext::Int(Some(self)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn i32_casts_to_int() { + assert_eq!(::CAST.as_str(), "int"); + } + + #[test] + fn i32_plaintext_sql_type_is_integer() { + assert_eq!( + ::PLAINTEXT_SQL_TYPE.as_str(), + "integer" + ); + } + + #[test] + fn i32_to_plaintext_wraps_in_int_variant() { + // The trait must lift the raw i32 into the EQL pipeline's Plaintext + // enum so the fixture driver can hand it to `eql::encrypt_eql`. + match (42_i32).to_plaintext() { + Plaintext::Int(Some(value)) => assert_eq!(value, 42), + other => panic!("expected Plaintext::Int(Some(42)), got {other:?}"), + } + } +} diff --git a/tests/sqlx/src/fixtures/eql_v2_int4.rs b/tests/sqlx/src/fixtures/eql_v2_int4.rs new file mode 100644 index 00000000..f32e93a5 --- /dev/null +++ b/tests/sqlx/src/fixtures/eql_v2_int4.rs @@ -0,0 +1,51 @@ +//! The `eql_v2_int4` fixture — the framework's reference example and proof. +//! +//! 14 integers spanning a negative boundary and small/medium/large/extreme +//! magnitudes. The generated `tests/sqlx/fixtures/eql_v2_int4.sql` is a plain +//! `jsonb`-payload table with no EQL dependency; #225 layers the `eql_v2_int4` +//! domain on top by casting `payload` per query. + +use super::spec::FixtureSpec; + +/// 14 values: a negative boundary plus small/medium/large/extreme magnitudes, +/// chosen so range pivots produce distinct cardinalities. +const VALUES: &[i32] = &[-100, -1, 1, 2, 5, 10, 17, 25, 42, 50, 100, 250, 1000, 9999]; + +/// The complete fixture definition. `.with_index("unique")` drives `=` / `<>` +/// (HMAC); `.with_index("ore")` drives `<` `<=` `>` `>=` (ORE block terms). +pub fn spec() -> FixtureSpec<'static, i32> { + FixtureSpec::new("eql_v2_int4") + .with_index("unique") + .with_index("ore") + .with_column_type("jsonb") + .with_values(VALUES) +} + +/// The generator. Gated by `fixture-gen` so `cargo test` never compiles it; +/// `#[ignore]` is a second guard. Run via `mise run fixture:generate eql_v2_int4`. +#[cfg(feature = "fixture-gen")] +#[tokio::test] +#[ignore = "generator — run via `mise run fixture:generate`"] +async fn generate() -> anyhow::Result<()> { + spec().run().await +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn spec_is_complete() { + assert!(spec().check_complete().is_ok()); + } + + #[test] + fn spec_has_14_values() { + assert_eq!(spec().values().len(), 14); + } + + #[test] + fn spec_includes_negative_values() { + assert!(spec().values().iter().any(|&v| v < 0)); + } +} diff --git a/tests/sqlx/src/fixtures/mod.rs b/tests/sqlx/src/fixtures/mod.rs new file mode 100644 index 00000000..d2c90c3f --- /dev/null +++ b/tests/sqlx/src/fixtures/mod.rs @@ -0,0 +1,21 @@ +//! Type-checked fixture generation framework. +//! +//! A fixture is one Rust file under `src/fixtures/` declaring a `FixtureSpec`. +//! `FixtureSpec::run()` generates the committed SQLx fixture script +//! `tests/sqlx/fixtures/.sql`. + +pub mod validation; + +pub mod eql_plaintext; + +pub use eql_plaintext::EqlPlaintext; + +pub mod spec; + +pub use spec::FixtureSpec; + +pub mod cipherstash; + +pub mod driver; + +pub mod eql_v2_int4; diff --git a/tests/sqlx/src/fixtures/spec.rs b/tests/sqlx/src/fixtures/spec.rs new file mode 100644 index 00000000..35e82615 --- /dev/null +++ b/tests/sqlx/src/fixtures/spec.rs @@ -0,0 +1,366 @@ +//! `FixtureSpec` — the type-checked fixture plug-in contract. +//! +//! `T` is the Rust plaintext type, inferred from `.with_values()`. Everything +//! not derivable — the indexes, the committed `payload` column type, the +//! data — is explicit. The fixture name drives every path by convention: +//! - table `fixtures.` +//! - working table `public._fixture_` +//! - script `tests/sqlx/fixtures/.sql` +//! - SQLx ref `scripts("")` +//! +//! Token-safety is enforced **at construction**: `new`, `.with_index`, and +//! `.with_column_type` each validate via the newtype `TryFrom` and **panic** +//! on a violation, so the builder stays a fluent chain (no `Result`, no +//! `?`). Because the spec stores validated newtypes (`FixtureIdentifier`, +//! `ColumnType`) and uses them via `Display` in the SQL renderers, an +//! unvalidated `&str` cannot reach a generated SQL string. `T::CAST` / +//! `T::PLAINTEXT_SQL_TYPE` are typed const newtypes (`Cast`, +//! `PlaintextSqlType`) — their allowlists are structural, so no runtime +//! check is needed. `check_complete()` covers only the completeness checks +//! (non-empty indexes/values) that the builder cannot make until the chain +//! is finished. + +use super::eql_plaintext::EqlPlaintext; +use super::validation::{ColumnType, FixtureIdentifier}; + +/// A fully specified fixture, ready to `.run()`. +pub struct FixtureSpec<'a, T> { + name: FixtureIdentifier, + indexes: Vec, + column_type: ColumnType, + values: &'a [T], +} + +impl<'a, T> FixtureSpec<'a, T> { + /// Start a spec. `name` must match `^[a-z][a-z0-9_]*$` — it becomes a SQL + /// identifier and a filename. Other fields take defaults until set: + /// `column_type` defaults to `"jsonb"`, `indexes`/`values` to empty. + /// + /// # Panics + /// Panics if `name` is not a valid identifier. + pub fn new(name: &str) -> Self { + let name = + FixtureIdentifier::try_from(name).unwrap_or_else(|e| panic!("fixture name: {e}")); + let column_type = ColumnType::try_from("jsonb") + .expect("default column type \"jsonb\" must be in the allowlist"); + Self { + name, + indexes: Vec::new(), + column_type, + values: &[], + } + } + + /// Add a search index (`"unique"`, `"ore"`, ...). Chainable. + /// + /// # Panics + /// Panics if `index_name` is not a valid identifier. + pub fn with_index(mut self, index_name: &str) -> Self { + let id = + FixtureIdentifier::try_from(index_name).unwrap_or_else(|e| panic!("index name: {e}")); + self.indexes.push(id); + self + } + + /// Set the committed `payload` column SQL type. Defaults to `"jsonb"`. + /// + /// # Panics + /// Panics if `column_type` is not in `validation::ALLOWED_COLUMN_TYPES`. + pub fn with_column_type(mut self, column_type: &str) -> Self { + self.column_type = + ColumnType::try_from(column_type).unwrap_or_else(|e| panic!("column type: {e}")); + self + } + + /// Set the plaintext value list. `T` is inferred and bound here, so this + /// is where `T::CAST` and `T::PLAINTEXT_SQL_TYPE` become known. Their + /// allowlists are structural (typed-const newtypes), so no runtime + /// validation is needed at this point. + pub fn with_values(mut self, values: &'a [T]) -> Self + where + T: EqlPlaintext, + { + self.values = values; + self + } + + // ----- accessors used by SQL rendering / the driver ----- + + pub fn name(&self) -> &str { + self.name.as_str() + } + + pub fn indexes(&self) -> &[FixtureIdentifier] { + &self.indexes + } + + pub fn column_type(&self) -> &ColumnType { + &self.column_type + } + + /// The plaintext value slice. + pub fn values(&self) -> &[T] { + self.values + } + + /// `fixtures.` — the committed fixture table. + pub fn fixture_table(&self) -> String { + format!("fixtures.{}", self.name) + } + + /// `_fixture_` — the transient working table (unqualified `public`). + pub fn working_table(&self) -> String { + format!("_fixture_{}", self.name) + } + + /// `.sql` — the generated script filename (relative to fixtures dir). + pub fn script_filename(&self) -> String { + format!("{}.sql", self.name) + } + + /// SQL for the transient working table on the generation database. + /// `id BIGINT PRIMARY KEY`, `plaintext` as the SQL type for `T`, and a + /// plain `payload jsonb` staging column. The fixture driver encrypts in + /// Rust via `cipherstash-client` and inserts the resulting JSONB directly + /// — the working table is a values buffer that exists only so the render + /// step can use Postgres `format('%L', …)` for SQL literal escaping. No + /// `eql_v2_configuration` writes, no EQL types — the working table has + /// no EQL dependency at all. + /// + /// The leading `DROP TABLE IF EXISTS` is belt-and-suspenders: a normal run + /// drops the working table itself at the end of `run()`, so this only + /// matters when a prior run crashed before its own teardown. + pub fn working_schema_sql(&self) -> String + where + T: EqlPlaintext, + { + let working = self.working_table(); + format!( + "DROP TABLE IF EXISTS public.{working};\n\ + CREATE TABLE public.{working} (\n \ + id BIGINT PRIMARY KEY,\n \ + plaintext {plaintext_type} NOT NULL,\n \ + payload jsonb\n);\n", + plaintext_type = T::PLAINTEXT_SQL_TYPE, + ) + } + + /// The committed fixture script's header + schema + DDL, up to (not + /// including) the rendered INSERT rows. The driver appends the INSERTs. + /// `payload` uses the committed `column_type` (`jsonb` for #224), not + /// `eql_v2_encrypted`; `plaintext` uses the SQL type for `T`. + pub fn fixture_script_preamble(&self) -> String + where + T: EqlPlaintext, + { + format!( + "-- AUTO-GENERATED by `mise run fixture:generate {name}`.\n\ + -- DO NOT EDIT BY HAND. Re-run the generator to refresh.\n\ + --\n\ + -- Encrypted via cipherstash-client (HMAC + ORE block terms).\n\ + -- A SQLx fixture script: opt in with\n\ + -- #[sqlx::test(fixtures(path = \"../fixtures\", scripts(\"{name}\")))]\n\ + \n\ + CREATE SCHEMA IF NOT EXISTS fixtures;\n\ + DROP TABLE IF EXISTS {table};\n\ + CREATE TABLE {table} (\n \ + id BIGINT PRIMARY KEY,\n \ + plaintext {plaintext_type} NOT NULL,\n \ + payload {column_type} NOT NULL\n);\n\n", + name = self.name, + table = self.fixture_table(), + plaintext_type = T::PLAINTEXT_SQL_TYPE, + column_type = self.column_type, + ) + } + + /// SQL run on the *direct* connection to render each working-table row as + /// a committed INSERT. `format('%L', ...)` does server-side literal + /// escaping; row values never pass through Rust string interpolation. + /// `payload::text` projects the already-encrypted JSONB straight through + /// — the working table stores the cipherstash-client-encrypted payload as + /// plain `jsonb`, so no composite unwrap is needed. + pub fn render_rows_sql(&self) -> String { + format!( + "SELECT format(\n \ + 'INSERT INTO {table} (id, plaintext, payload) VALUES (%L, %L, %L::{column_type});',\n \ + id, plaintext, payload::text\n) \ + FROM public.{working} ORDER BY id", + table = self.fixture_table(), + column_type = self.column_type, + working = self.working_table(), + ) + } + + /// Check the spec is *complete*: it has at least one index and at least + /// one value. These cannot be checked at construction — the builder does + /// not know when the chain is finished — so the driver calls this before + /// generating any SQL. Token safety is already guaranteed by the + /// `FixtureIdentifier`/`ColumnType` newtypes; this method covers only what + /// construction cannot. + pub fn check_complete(&self) -> anyhow::Result<()> { + if self.indexes.is_empty() { + anyhow::bail!("fixture {:?} declares no indexes", self.name.as_str()); + } + if self.values.is_empty() { + anyhow::bail!("fixture {:?} has no values", self.name.as_str()); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn int4_spec() -> FixtureSpec<'static, i32> { + const VALUES: &[i32] = &[-1, 1, 42]; + FixtureSpec::new("eql_v2_int4") + .with_index("unique") + .with_index("ore") + .with_column_type("jsonb") + .with_values(VALUES) + } + + #[test] + fn derives_paths_from_the_name() { + let s = int4_spec(); + assert_eq!(s.fixture_table(), "fixtures.eql_v2_int4"); + assert_eq!(s.working_table(), "_fixture_eql_v2_int4"); + assert_eq!(s.script_filename(), "eql_v2_int4.sql"); + } + + #[test] + fn records_indexes_in_order() { + let s = int4_spec(); + let names: Vec<&str> = s.indexes().iter().map(FixtureIdentifier::as_str).collect(); + assert_eq!(names, vec!["unique", "ore"]); + } + + #[test] + fn column_type_defaults_to_jsonb() { + const V: &[i32] = &[1]; + let s = FixtureSpec::new("x").with_index("unique").with_values(V); + assert_eq!(s.column_type().as_str(), "jsonb"); + } + + #[test] + fn valid_spec_passes_completeness_check() { + assert!(int4_spec().check_complete().is_ok()); + } + + #[test] + #[should_panic(expected = "is not a valid identifier")] + fn validation_rejects_a_bad_name() { + // A bad name panics at construction, before the chain continues. + let _ = FixtureSpec::<'static, i32>::new("Bad-Name"); + } + + #[test] + #[should_panic(expected = "is not in the allowlist")] + fn validation_rejects_a_non_allowlisted_column_type() { + // A non-allowlisted column type panics in `.with_column_type()`. + let _ = FixtureSpec::<'static, i32>::new("x").with_column_type("text"); + } + + #[test] + #[should_panic(expected = "is not a valid identifier")] + fn validation_rejects_a_bad_index_name() { + // A bad index name panics in `.with_index()`. + let _ = FixtureSpec::<'static, i32>::new("x").with_index("BAD IX"); + } + + #[test] + fn completeness_rejects_a_spec_with_no_indexes() { + const V: &[i32] = &[1]; + let s = FixtureSpec::new("x").with_values(V); + assert!(s.check_complete().is_err()); + } + + #[test] + fn completeness_rejects_a_spec_with_no_values() { + const V: &[i32] = &[]; + let s = FixtureSpec::new("x").with_index("unique").with_values(V); + assert!(s.check_complete().is_err()); + } + + #[test] + fn working_schema_sql_drops_and_creates_the_working_table() { + let sql = int4_spec().working_schema_sql(); + assert!(sql.contains("DROP TABLE IF EXISTS public._fixture_eql_v2_int4;")); + assert!(sql.contains("CREATE TABLE public._fixture_eql_v2_int4 (")); + assert!(sql.contains("id BIGINT PRIMARY KEY")); + assert!(sql.contains("plaintext integer NOT NULL")); + // The working table's payload is plain jsonb — encryption happens in + // Rust via cipherstash-client, not via a Proxy round trip. + assert!(sql.contains("payload jsonb")); + assert!( + !sql.contains("eql_v2_encrypted"), + "working table should not depend on the eql_v2_encrypted type" + ); + } + + #[test] + fn working_schema_sql_does_not_touch_eql_configuration() { + // The cipherstash-client path does NOT write to eql_v2_configuration: + // ColumnConfig lives entirely in Rust, no add_search_config / + // remove_search_config calls are emitted, and the working table has + // no EQL dependency. + let sql = int4_spec().working_schema_sql(); + assert!(!sql.contains("add_search_config")); + assert!(!sql.contains("remove_search_config")); + assert!(!sql.contains("eql_v2_configuration")); + } + + #[test] + fn fixture_script_preamble_renders_the_committed_table() { + let preamble = int4_spec().fixture_script_preamble(); + // header + assert!(preamble.contains("AUTO-GENERATED")); + assert!(preamble.contains("DO NOT EDIT BY HAND")); + assert!(preamble.contains("mise run fixture:generate eql_v2_int4")); + assert!(preamble.contains("HMAC + ORE block terms")); + // schema + table in the fixtures schema, jsonb payload + assert!(preamble.contains("CREATE SCHEMA IF NOT EXISTS fixtures;")); + assert!(preamble.contains("DROP TABLE IF EXISTS fixtures.eql_v2_int4;")); + assert!(preamble.contains("CREATE TABLE fixtures.eql_v2_int4 (")); + assert!(preamble.contains("id BIGINT PRIMARY KEY")); + assert!(preamble.contains("plaintext integer NOT NULL")); + assert!(preamble.contains("payload jsonb NOT NULL")); + } + + #[test] + fn fixture_script_preamble_attributes_encryption_to_cipherstash_client() { + // The preamble must record the encryption path so a reader of the + // committed SQL can trace it back to the generator. + let preamble = int4_spec().fixture_script_preamble(); + assert!(preamble.contains("cipherstash-client")); + assert!( + !preamble.contains("CipherStash Proxy"), + "preamble must not credit the Proxy — encryption is direct now" + ); + } + + #[test] + fn fixture_script_preamble_uses_the_committed_column_type() { + // The committed table uses .with_column_type(), NOT eql_v2_encrypted. + let preamble = int4_spec().fixture_script_preamble(); + assert!(!preamble.contains("eql_v2_encrypted")); + } + + #[test] + fn render_rows_sql_projects_format_l_over_the_working_table() { + let sql = int4_spec().render_rows_sql(); + assert!(sql.contains("INSERT INTO fixtures.eql_v2_int4 (id, plaintext, payload) VALUES")); + assert!(sql.contains("%L, %L, %L::jsonb")); + assert!(sql.contains("FROM public._fixture_eql_v2_int4")); + // payload is already encrypted JSONB in the working table; no + // composite to unwrap. + assert!(sql.contains("payload::text")); + assert!( + !sql.contains("(payload).data"), + "render must not unwrap a composite — payload is plain jsonb" + ); + assert!(sql.contains("ORDER BY id")); + } +} diff --git a/tests/sqlx/src/fixtures/validation.rs b/tests/sqlx/src/fixtures/validation.rs new file mode 100644 index 00000000..e641a726 --- /dev/null +++ b/tests/sqlx/src/fixtures/validation.rs @@ -0,0 +1,129 @@ +//! Pure SQL-token validators. Validated tokens are wrapped in newtypes +//! (`FixtureIdentifier`, `ColumnType`) so a renderer that accepts the newtype +//! receives type-level proof of validation — an unvalidated `&str` cannot +//! reach the renderer's format strings. + +use std::fmt; + +/// Lowercase snake-case identifier, must start with a letter: `^[a-z][a-z0-9_]*$`. +fn is_valid_identifier(s: &str) -> bool { + let mut chars = s.chars(); + match chars.next() { + Some(c) if c.is_ascii_lowercase() => {} + _ => return false, + } + chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_') +} + +/// Allowlist of committed `payload` column types. `{ jsonb }` for #224 — no +/// domain types exist yet. Extending to domain-typed fixtures means extending +/// this list with validated, optionally schema-qualified type tokens. +pub const ALLOWED_COLUMN_TYPES: &[&str] = &["jsonb"]; + +fn is_valid_column_type(s: &str) -> bool { + ALLOWED_COLUMN_TYPES.contains(&s) +} + +/// A validated SQL identifier. Construction proves the string matches +/// `^[a-z][a-z0-9_]*$`. Renderers interpolate via `Display`, so the bare +/// `&str` cannot reach generated SQL once it has been validated into this type. +#[derive(Debug, Clone)] +pub struct FixtureIdentifier(String); + +impl FixtureIdentifier { + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl TryFrom<&str> for FixtureIdentifier { + type Error = String; + fn try_from(s: &str) -> Result { + if is_valid_identifier(s) { + Ok(Self(s.to_string())) + } else { + Err(format!( + "{s:?} is not a valid identifier (^[a-z][a-z0-9_]*$)" + )) + } + } +} + +impl fmt::Display for FixtureIdentifier { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } +} + +/// A validated committed-payload column type token. Construction proves the +/// string is in `ALLOWED_COLUMN_TYPES`. +#[derive(Debug, Clone)] +pub struct ColumnType(String); + +impl ColumnType { + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl TryFrom<&str> for ColumnType { + type Error = String; + fn try_from(s: &str) -> Result { + if is_valid_column_type(s) { + Ok(Self(s.to_string())) + } else { + Err(format!( + "{s:?} is not in the allowlist {ALLOWED_COLUMN_TYPES:?}" + )) + } + } +} + +impl fmt::Display for ColumnType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn accepts_valid_identifiers() { + assert!(FixtureIdentifier::try_from("eql_v2_int4").is_ok()); + assert!(FixtureIdentifier::try_from("a").is_ok()); + assert!(FixtureIdentifier::try_from("x9_y").is_ok()); + } + + #[test] + fn rejects_invalid_identifiers() { + assert!(FixtureIdentifier::try_from("").is_err()); + assert!(FixtureIdentifier::try_from("9abc").is_err()); // leading digit + assert!(FixtureIdentifier::try_from("_abc").is_err()); // leading underscore + assert!(FixtureIdentifier::try_from("Abc").is_err()); // uppercase + assert!(FixtureIdentifier::try_from("a-b").is_err()); // hyphen + assert!(FixtureIdentifier::try_from("a b").is_err()); // space + assert!(FixtureIdentifier::try_from("a;DROP").is_err()); // injection attempt + } + + #[test] + fn identifier_renders_via_display() { + let id = FixtureIdentifier::try_from("eql_v2_int4").unwrap(); + assert_eq!(format!("{id}"), "eql_v2_int4"); + } + + #[test] + fn column_type_accepts_jsonb_only() { + assert!(ColumnType::try_from("jsonb").is_ok()); + assert!(ColumnType::try_from("text").is_err()); + assert!(ColumnType::try_from("eql_v2_int4").is_err()); + assert!(ColumnType::try_from("jsonb; DROP TABLE x").is_err()); + } + + #[test] + fn column_type_renders_via_display() { + let ct = ColumnType::try_from("jsonb").unwrap(); + assert_eq!(format!("{ct}"), "jsonb"); + } +} diff --git a/tests/sqlx/src/lib.rs b/tests/sqlx/src/lib.rs index 911264c3..2f915e37 100644 --- a/tests/sqlx/src/lib.rs +++ b/tests/sqlx/src/lib.rs @@ -5,6 +5,7 @@ use sqlx::PgPool; pub mod assertions; +pub mod fixtures; pub mod helpers; pub mod index_types; pub mod selectors; diff --git a/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs b/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs new file mode 100644 index 00000000..3cf73225 --- /dev/null +++ b/tests/sqlx/tests/eql_v2_int4_fixture_tests.rs @@ -0,0 +1,133 @@ +//! Structural verification of the generated `eql_v2_int4` fixture. +//! +//! Vanilla SQL over `fixtures.eql_v2_int4` — `payload` is plain `jsonb`, no +//! domain type required. The `plaintext` column is the in-table oracle; no +//! Rust value constant is shared with the generator. #224 verifies the +//! fixture is well-formed; #225 verifies the domain operators on it. + +use anyhow::Result; +use sqlx::PgPool; + +/// The 14 values from `src/fixtures/eql_v2_int4.rs`, in id order. Kept here +/// only to assert the in-table `plaintext` oracle matches what was generated. +/// If `plaintext_column_matches_the_generated_values` fails, the generator's +/// `VALUES` and this constant have drifted — re-run +/// `mise run fixture:generate eql_v2_int4` and update this list to match. +const EXPECTED_PLAINTEXTS: &[i32] = &[-100, -1, 1, 2, 5, 10, 17, 25, 42, 50, 100, 250, 1000, 9999]; + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn fixture_has_fourteen_rows(pool: PgPool) -> Result<()> { + let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM fixtures.eql_v2_int4") + .fetch_one(&pool) + .await?; + assert_eq!(count, 14, "eql_v2_int4 fixture should have 14 rows"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn ids_are_sequential_one_to_fourteen(pool: PgPool) -> Result<()> { + let ids: Vec = sqlx::query_scalar("SELECT id FROM fixtures.eql_v2_int4 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!(ids, (1..=14).collect::>()); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn plaintext_column_matches_the_generated_values(pool: PgPool) -> Result<()> { + let plaintexts: Vec = + sqlx::query_scalar("SELECT plaintext FROM fixtures.eql_v2_int4 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!(plaintexts, EXPECTED_PLAINTEXTS); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_the_hmac_equality_term(pool: PgPool) -> Result<()> { + // `hm` drives equality. Every row's payload must carry an `hm` string term. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'hm' IS NULL OR jsonb_typeof(payload->'hm') <> 'string'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(missing, 0, "every payload must carry an `hm` string term"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_the_ore_block_term(pool: PgPool) -> Result<()> { + // `ob` drives ordering. Every row's payload must carry a non-null ob array. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'ob' IS NULL OR jsonb_typeof(payload->'ob') <> 'array'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(missing, 0, "every payload must carry an `ob` array term"); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_carries_a_ciphertext(pool: PgPool) -> Result<()> { + // `c` is the ciphertext. Every row's payload must carry a `c` string. + let missing: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'c' IS NULL OR jsonb_typeof(payload->'c') <> 'string'", + ) + .fetch_one(&pool) + .await?; + assert_eq!( + missing, 0, + "every payload must carry a `c` ciphertext string" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn plaintext_oracle_supports_value_filtering(pool: PgPool) -> Result<()> { + // The in-table `plaintext` oracle: a consuming test can filter on it + // directly. Exactly one row has plaintext = 42. + let ids: Vec = + sqlx::query_scalar("SELECT id FROM fixtures.eql_v2_int4 WHERE plaintext = 42 ORDER BY id") + .fetch_all(&pool) + .await?; + assert_eq!( + ids, + vec![9], + "expected exactly one row with plaintext = 42 at id 9" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn hmac_equality_terms_are_distinct_for_distinct_values(pool: PgPool) -> Result<()> { + // All 14 plaintext values are distinct, so all 14 `hm` terms must be too. + let distinct_hm: i64 = + sqlx::query_scalar("SELECT COUNT(DISTINCT payload->>'hm') FROM fixtures.eql_v2_int4") + .fetch_one(&pool) + .await?; + assert_eq!( + distinct_hm, 14, + "14 distinct values -> 14 distinct hm terms" + ); + Ok(()) +} + +#[sqlx::test(fixtures(path = "../fixtures", scripts("eql_v2_int4")))] +async fn every_payload_declares_eql_payload_version_v2(pool: PgPool) -> Result<()> { + // The EQL `v` payload-format field is checked server-side against `'2'` + // when an `eql_v2_encrypted` value is inserted. Asserting equality here + // (not just presence) means a future bump to `v=3` fails this test + // loudly, forcing the maintainer to regenerate the fixture and audit + // consumers for v2→v3 semantic changes. + let mismatched: i64 = sqlx::query_scalar( + "SELECT COUNT(*) FROM fixtures.eql_v2_int4 + WHERE payload->'v' IS NULL OR payload->>'v' <> '2'", + ) + .fetch_one(&pool) + .await?; + assert_eq!(mismatched, 0, "every payload must declare v = '2'"); + Ok(()) +} diff --git a/tests/sqlx/tests/like_operator_tests.rs b/tests/sqlx/tests/like_operator_tests.rs index ad062727..679ee81d 100644 --- a/tests/sqlx/tests/like_operator_tests.rs +++ b/tests/sqlx/tests/like_operator_tests.rs @@ -53,7 +53,7 @@ async fn create_encrypted_json_with_index( }) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_operator_matches_pattern(pool: PgPool) -> Result<()> { // Test: ~~ operator (LIKE) matches encrypted values // Tests both ~~ operator and LIKE operator (they're equivalent) @@ -89,7 +89,7 @@ async fn like_operator_matches_pattern(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_operator_no_match(pool: PgPool) -> Result<()> { // Test: ~~ operator returns empty for non-matching pattern // This test verifies that LIKE operations correctly return no results @@ -109,7 +109,7 @@ async fn like_operator_no_match(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn like_function_matches_pattern(pool: PgPool) -> Result<()> { // Test: eql_v2.like() function // Tests the eql_v2.like() function which wraps bloom filter matching @@ -129,7 +129,7 @@ async fn like_function_matches_pattern(pool: PgPool) -> Result<()> { Ok(()) } -#[sqlx::test(fixtures(path = "../fixtures", scripts("like_data")))] +#[sqlx::test(fixtures(path = "../fixtures", scripts("match_data")))] async fn ilike_operator_case_insensitive_matches(pool: PgPool) -> Result<()> { // Test: ~~* operator (ILIKE) matches encrypted values (case-insensitive) // Tests both ~~* operator and ILIKE operator (they're equivalent)