From f65edf9c91520e3cce2f421c194c8cd7bb7f019f Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Sun, 21 Dec 2025 12:15:59 -0800 Subject: [PATCH] Add codex-network-proxy crate --- codex-rs/Cargo.lock | 1830 +++++++++++++--------- codex-rs/Cargo.toml | 3 + codex-rs/core/src/config/mod.rs | 6 + codex-rs/network-proxy/Cargo.toml | 43 + codex-rs/network-proxy/src/admin.rs | 108 ++ codex-rs/network-proxy/src/config.rs | 203 +++ codex-rs/network-proxy/src/http_proxy.rs | 446 ++++++ codex-rs/network-proxy/src/init.rs | 17 + codex-rs/network-proxy/src/lib.rs | 58 + codex-rs/network-proxy/src/main.rs | 8 + codex-rs/network-proxy/src/mitm.rs | 665 ++++++++ codex-rs/network-proxy/src/policy.rs | 31 + codex-rs/network-proxy/src/responses.rs | 65 + codex-rs/network-proxy/src/socks5.rs | 192 +++ codex-rs/network-proxy/src/state.rs | 350 +++++ docs/network-proxy-design.md | 102 ++ docs/network-proxy-quickstart.md | 93 ++ 17 files changed, 3471 insertions(+), 749 deletions(-) create mode 100644 codex-rs/network-proxy/Cargo.toml create mode 100644 codex-rs/network-proxy/src/admin.rs create mode 100644 codex-rs/network-proxy/src/config.rs create mode 100644 codex-rs/network-proxy/src/http_proxy.rs create mode 100644 codex-rs/network-proxy/src/init.rs create mode 100644 codex-rs/network-proxy/src/lib.rs create mode 100644 codex-rs/network-proxy/src/main.rs create mode 100644 codex-rs/network-proxy/src/mitm.rs create mode 100644 codex-rs/network-proxy/src/policy.rs create mode 100644 codex-rs/network-proxy/src/responses.rs create mode 100644 codex-rs/network-proxy/src/socks5.rs create mode 100644 codex-rs/network-proxy/src/state.rs create mode 100644 docs/network-proxy-design.md create mode 100644 docs/network-proxy-quickstart.md diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 62b4d4d9b1..39d7875b98 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -42,7 +42,7 @@ dependencies = [ "bitflags 2.10.0", "bytes", "bytestring", - "derive_more 2.0.1", + "derive_more 2.1.0", "encoding_rs", "foldhash 0.1.5", "futures-core", @@ -137,7 +137,7 @@ dependencies = [ "bytes", "bytestring", "cfg-if", - "derive_more 2.0.1", + "derive_more 2.1.0", "encoding_rs", "foldhash 0.1.5", "futures-core", @@ -162,9 +162,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -228,7 +228,7 @@ checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -261,7 +261,7 @@ version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67555e1f1ece39d737e28c8a017721287753af3f93225e4a445b29ccb0f5912c" dependencies = [ - "nom", + "nom 7.1.3", "ratatui", "simdutf8", "smallvec", @@ -270,9 +270,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -300,22 +300,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -330,7 +330,7 @@ version = "0.0.0" dependencies = [ "anyhow", "assert_cmd", - "base64", + "base64 0.22.1", "chrono", "codex-app-server-protocol", "codex-core", @@ -386,6 +386,45 @@ dependencies = [ "term", ] +[[package]] +name = "asn1-rs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.3", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "assert-json-diff" version = "2.0.2" @@ -398,13 +437,12 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.0.17" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +checksum = "bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85" dependencies = [ "anstyle", "bstr", - "doc-comment", "libc", "predicates", "predicates-core", @@ -480,9 +518,9 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.0.8", + "rustix 1.1.2", "slab", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -511,7 +549,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.0.8", + "rustix 1.1.2", ] [[package]] @@ -522,7 +560,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -537,10 +575,10 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.8", + "rustix 1.1.2", "signal-hook-registry", "slab", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -562,7 +600,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -579,7 +617,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -596,17 +634,17 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.3.1", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-util", "itoa", "matchit", @@ -614,8 +652,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "sync_wrapper", "tokio", "tower", @@ -625,18 +662,17 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -644,9 +680,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -654,9 +690,15 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -720,6 +762,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "blocking" version = "1.6.2" @@ -735,9 +786,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", @@ -746,15 +797,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -770,9 +821,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "bytestring" @@ -809,10 +860,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.30" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -824,9 +876,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -862,7 +914,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -883,9 +935,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -893,9 +945,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -906,30 +958,30 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.57" +version = "4.5.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad" +checksum = "39615915e2ece2550c0149addac32fb5bd312c657f43845bb9088cb9c8a7c992" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clipboard-win" @@ -967,7 +1019,7 @@ dependencies = [ "codex-protocol", "eventsource-stream", "futures", - "http 1.3.1", + "http 1.4.0", "pretty_assertions", "regex-lite", "reqwest", @@ -988,7 +1040,7 @@ dependencies = [ "anyhow", "app_test_support", "assert_cmd", - "base64", + "base64 0.22.1", "chrono", "codex-app-server-protocol", "codex-arg0", @@ -1012,7 +1064,7 @@ dependencies = [ "shlex", "tempfile", "tokio", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", "tracing", "tracing-subscriber", "uuid", @@ -1165,7 +1217,7 @@ dependencies = [ "supports-color 3.0.2", "tempfile", "tokio", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", "tracing", ] @@ -1177,7 +1229,7 @@ dependencies = [ "bytes", "eventsource-stream", "futures", - "http 1.3.1", + "http 1.4.0", "opentelemetry", "opentelemetry_sdk", "rand 0.9.2", @@ -1197,7 +1249,7 @@ version = "0.0.0" dependencies = [ "anyhow", "async-trait", - "base64", + "base64 0.22.1", "chrono", "clap", "codex-cloud-tasks-client", @@ -1245,7 +1297,7 @@ dependencies = [ "codex-ollama", "codex-protocol", "serde", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", ] [[package]] @@ -1257,7 +1309,7 @@ dependencies = [ "assert_matches", "async-channel", "async-trait", - "base64", + "base64 0.22.1", "chardetng", "chrono", "codex-api", @@ -1289,9 +1341,9 @@ dependencies = [ "escargot", "eventsource-stream", "futures", - "http 1.3.1", + "http 1.4.0", "image", - "indexmap 2.12.0", + "indexmap 2.12.1", "keyring", "landlock", "libc", @@ -1324,7 +1376,7 @@ dependencies = [ "tokio", "tokio-test", "tokio-util", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", "toml_edit", "tracing", "tracing-subscriber", @@ -1421,7 +1473,7 @@ dependencies = [ "allocative", "anyhow", "clap", - "derive_more 2.0.1", + "derive_more 2.1.0", "env_logger", "log", "multimap", @@ -1514,7 +1566,7 @@ name = "codex-login" version = "0.0.0" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "chrono", "codex-app-server-protocol", "codex-core", @@ -1560,6 +1612,28 @@ dependencies = [ "wiremock", ] +[[package]] +name = "codex-network-proxy" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "codex-core", + "globset", + "hyper 0.14.32", + "rcgen", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "rustls-pemfile", + "serde", + "serde_json", + "tokio", + "tokio-rustls 0.24.1", + "toml 0.9.9+spec-1.0.0", + "tracing", + "tracing-subscriber", +] + [[package]] name = "codex-ollama" version = "0.0.0" @@ -1586,7 +1660,7 @@ dependencies = [ "codex-protocol", "codex-utils-absolute-path", "eventsource-stream", - "http 1.3.1", + "http 1.4.0", "opentelemetry", "opentelemetry-appender-tracing", "opentelemetry-otlp", @@ -1702,7 +1776,7 @@ dependencies = [ "anyhow", "arboard", "assert_matches", - "base64", + "base64 0.22.1", "chrono", "clap", "codex-ansi-escape", @@ -1719,7 +1793,7 @@ dependencies = [ "codex-windows-sandbox", "color-eyre", "crossterm", - "derive_more 2.0.1", + "derive_more 2.1.0", "diffy", "dirs", "dunce", @@ -1749,7 +1823,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -1770,7 +1844,7 @@ dependencies = [ "arboard", "assert_matches", "async-stream", - "base64", + "base64 0.22.1", "chrono", "clap", "codex-ansi-escape", @@ -1788,7 +1862,7 @@ dependencies = [ "codex-windows-sandbox", "color-eyre", "crossterm", - "derive_more 2.0.1", + "derive_more 2.1.0", "diffy", "dirs", "dunce", @@ -1818,7 +1892,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -1856,7 +1930,7 @@ dependencies = [ name = "codex-utils-image" version = "0.0.0" dependencies = [ - "base64", + "base64 0.22.1", "codex-utils-cache", "image", "tempfile", @@ -1870,7 +1944,7 @@ version = "0.0.0" dependencies = [ "pretty_assertions", "serde_json", - "toml 0.9.5", + "toml 0.9.9+spec-1.0.0", ] [[package]] @@ -1907,7 +1981,7 @@ name = "codex-windows-sandbox" version = "0.0.0" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "chrono", "codex-protocol", "codex-utils-absolute-path", @@ -2011,9 +2085,9 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.7.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -2050,7 +2124,7 @@ version = "0.0.0" dependencies = [ "anyhow", "assert_cmd", - "base64", + "base64 0.22.1", "codex-core", "codex-protocol", "codex-utils-absolute-path", @@ -2151,9 +2225,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -2216,7 +2290,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2230,7 +2304,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2241,7 +2315,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2252,14 +2326,20 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] -name = "dbus" -version = "0.9.9" +name = "data-encoding" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190b6255e8ab55a7b568df5a883e9497edc3e4821c06396612048b430e5ad1e9" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "dbus" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b3aa68d7e7abee336255bd7248ea965cc393f3e70411135a6f6a4b651345d4" dependencies = [ "libc", "libdbus-sys", @@ -2334,10 +2414,24 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.5.4" +name = "der-parser" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.3", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", "serde_core", @@ -2365,11 +2459,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl 2.1.0", ] [[package]] @@ -2381,20 +2475,21 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "unicode-xid", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" dependencies = [ - "convert_case 0.7.1", + "convert_case 0.10.0", "proc-macro2", "quote", - "syn 2.0.104", + "rustc_version", + "syn 2.0.111", "unicode-xid", ] @@ -2457,8 +2552,8 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users 0.5.0", - "windows-sys 0.61.1", + "redox_users 0.5.2", + "windows-sys 0.61.2", ] [[package]] @@ -2500,15 +2595,9 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "dotenvy" version = "0.15.7" @@ -2523,9 +2612,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dtor" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" dependencies = [ "dtor-proc-macro", ] @@ -2559,14 +2648,14 @@ checksum = "83e195b4945e88836d826124af44fdcb262ec01ef94d44f14f4fb5103f19892a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" @@ -2600,9 +2689,9 @@ dependencies = [ [[package]] name = "endi" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] name = "endian-type" @@ -2628,7 +2717,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2639,9 +2728,9 @@ checksum = "dbfd0e7fc632dec5e6c9396a27bc9f9975b4e039720e1fd3e34021d3ce28c415" [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -2677,12 +2766,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2704,9 +2793,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -2730,7 +2819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" dependencies = [ "futures-core", - "nom", + "nom 7.1.3", "pin-project-lite", ] @@ -2779,7 +2868,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -2789,7 +2878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.0.8", + "rustix 1.1.2", "windows-sys 0.59.0", ] @@ -2813,6 +2902,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "findshlibs" version = "0.10.2" @@ -2827,9 +2922,9 @@ dependencies = [ [[package]] name = "fixed_decimal" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35943d22b2f19c0cb198ecf915910a8158e94541c89dcc63300d7799d46c2c5e" +checksum = "35eabf480f94d69182677e37571d3be065822acfafd12f2f085db44fbbcc8e57" dependencies = [ "displaydoc", "smallvec", @@ -2843,10 +2938,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] -name = "flate2" -version = "1.1.2" +name = "fixedbitset" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -2896,9 +2997,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -2981,7 +3082,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -3035,19 +3136,19 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "libc", - "windows-targets 0.48.5", + "rustix 1.1.2", + "windows-link 0.2.1", ] [[package]] name = "getopts" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width 0.2.1", ] @@ -3061,56 +3162,75 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "globset" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", "log", "regex-automata", - "regex-syntax 0.8.5", + "regex-syntax 0.8.8", ] [[package]] name = "h2" -version = "0.4.11" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.12.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.3.1", - "indexmap 2.12.0", + "http 1.4.0", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -3119,12 +3239,13 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -3145,9 +3266,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -3156,9 +3277,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", @@ -3203,22 +3324,22 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "hostname" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" dependencies = [ "cfg-if", "libc", - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] @@ -3234,15 +3355,25 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -3250,7 +3381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http 1.4.0", ] [[package]] @@ -3261,8 +3392,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -3280,17 +3411,41 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.7.0" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", - "h2", - "http 1.3.1", - "http-body", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -3307,14 +3462,14 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.3.1", - "hyper", + "http 1.4.0", + "hyper 1.8.1", "hyper-util", - "rustls", - "rustls-native-certs", + "rustls 0.23.35", + "rustls-native-certs 0.8.2", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower-service", "webpki-roots", ] @@ -3325,7 +3480,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper", + "hyper 1.8.1", "hyper-util", "pin-project-lite", "tokio", @@ -3340,7 +3495,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-util", "native-tls", "tokio", @@ -3350,23 +3505,23 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http 1.3.1", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.1", "system-configuration", "tokio", "tower-service", @@ -3376,9 +3531,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3386,7 +3541,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -3489,9 +3644,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -3503,9 +3658,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -3532,9 +3687,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -3553,9 +3708,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.23" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" dependencies = [ "crossbeam-deque", "globset", @@ -3580,7 +3735,7 @@ dependencies = [ "png", "tiff", "zune-core 0.5.0", - "zune-jpeg 0.5.5", + "zune-jpeg 0.5.7", ] [[package]] @@ -3591,9 +3746,9 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" [[package]] name = "indenter" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" @@ -3608,21 +3763,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "serde", "serde_core", ] [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "inotify" @@ -3667,37 +3825,26 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a" +checksum = "6778b0196eefee7df739db78758e5cf9b37412268bfa5650bfeed028aed20d9c" dependencies = [ "darling 0.20.11", "indoc", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "inventory" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" dependencies = [ "rustversion", ] -[[package]] -name = "io-uring" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -3706,9 +3853,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -3716,13 +3863,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3733,9 +3880,9 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -3772,26 +3919,26 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -3818,9 +3965,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -3877,7 +4024,7 @@ dependencies = [ "is-terminal", "itertools 0.10.5", "lalrpop-util", - "petgraph", + "petgraph 0.6.5", "regex", "regex-syntax 0.6.29", "string_cache", @@ -3897,9 +4044,9 @@ dependencies = [ [[package]] name = "landlock" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d2ef408b88e913bfc6594f5e693d57676f6463ded7d8bf994175364320c706" +checksum = "49fefd6652c57d68aaa32544a4c0e642929725bdc1fd929367cdeb673ab81088" dependencies = [ "enumflags2", "libc", @@ -3920,24 +4067,24 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libdbus-sys" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbe856efeb50e4681f010e9aaa2bf0a644e10139e54cde10fc83a307c23bd9f" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" dependencies = [ "pkg-config", ] [[package]] name = "libredox" -version = "0.1.6" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0" +checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" dependencies = [ "bitflags 2.10.0", "libc", @@ -3961,15 +4108,15 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "local-waker" @@ -3979,19 +4126,18 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos" @@ -4022,7 +4168,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", ] [[package]] @@ -4031,7 +4177,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" dependencies = [ - "hashbrown 0.16.0", + "hashbrown 0.16.1", ] [[package]] @@ -4105,9 +4251,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -4161,21 +4307,21 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "moxcms" -version = "0.7.5" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" dependencies = [ "num-traits", "pxfm", @@ -4275,6 +4421,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -4307,11 +4462,11 @@ checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4428,10 +4583,10 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "getrandom 0.2.16", - "http 1.3.1", + "http 1.4.0", "rand 0.8.5", "reqwest", "serde", @@ -4444,18 +4599,18 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" dependencies = [ "objc2-encode", ] [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.10.0", "objc2", @@ -4464,10 +4619,31 @@ dependencies = [ ] [[package]] -name = "objc2-core-foundation" -version = "0.3.1" +name = "objc2-cloud-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.10.0", "dispatch2", @@ -4476,9 +4652,9 @@ dependencies = [ [[package]] name = "objc2-core-graphics" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.10.0", "dispatch2", @@ -4487,6 +4663,38 @@ dependencies = [ "objc2-io-surface", ] +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + [[package]] name = "objc2-encode" version = "4.1.0" @@ -4495,20 +4703,22 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", + "block2", + "libc", "objc2", "objc2-core-foundation", ] [[package]] name = "objc2-io-surface" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.10.0", "objc2", @@ -4516,14 +4726,66 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.7" +name = "objc2-quartz-core" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] +[[package]] +name = "oid-registry" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -4532,15 +4794,15 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ "bitflags 2.10.0", "cfg-if", @@ -4559,7 +4821,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -4570,18 +4832,18 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-src" -version = "300.5.1+3.5.1" +version = "300.5.4+3.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" +checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -4624,7 +4886,7 @@ checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d" dependencies = [ "async-trait", "bytes", - "http 1.3.1", + "http 1.4.0", "opentelemetry", "reqwest", ] @@ -4635,7 +4897,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b" dependencies = [ - "http 1.3.1", + "http 1.4.0", "opentelemetry", "opentelemetry-http", "opentelemetry-proto", @@ -4655,7 +4917,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc" dependencies = [ - "base64", + "base64 0.22.1", "hex", "opentelemetry", "opentelemetry_sdk", @@ -4706,31 +4968,35 @@ dependencies = [ [[package]] name = "os_info" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3" +checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" dependencies = [ + "android_system_properties", "log", - "plist", + "nix 0.30.1", + "objc2", + "objc2-foundation", + "objc2-ui-kit", "serde", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "os_pipe" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db335f4760b14ead6290116f2427bf33a14d4f0617d49f78a246de10c1831224" +checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "owo-colors" -version = "4.2.2" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" dependencies = [ "supports-color 2.1.0", "supports-color 3.0.2", @@ -4744,9 +5010,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -4754,15 +5020,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -4773,9 +5039,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pastey" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d6c094ee800037dff99e02cab0eaf3142826586742a270ab3d7a62656bd27a" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" [[package]] name = "path-absolutize" @@ -4801,6 +5067,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64 0.22.1", + "serde_core", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -4812,9 +5088,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" @@ -4822,8 +5098,19 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", - "indexmap 2.12.0", + "fixedbitset 0.4.2", + "indexmap 2.12.1", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap 2.12.1", ] [[package]] @@ -4852,7 +5139,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -4884,19 +5171,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plist" -version = "1.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" -dependencies = [ - "base64", - "indexmap 2.12.0", - "quick-xml 0.38.0", - "serde", - "time", -] - [[package]] name = "png" version = "0.18.0" @@ -4920,8 +5194,8 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.8", - "windows-sys 0.61.1", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -5043,9 +5317,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -5057,7 +5331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1" dependencies = [ "futures", - "indexmap 2.12.0", + "indexmap 2.12.1", "nix 0.30.1", "tokio", "tracing", @@ -5084,7 +5358,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -5108,9 +5382,9 @@ checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" [[package]] name = "pxfm" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55f4fedc84ed39cb7a489322318976425e42a147e2be79d8f878e2884f94e84" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" dependencies = [ "num-traits", ] @@ -5130,15 +5404,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quick-xml" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8927b0664f5c5a98265138b7e3f90aa19a6b21353182469ace36d4ac527b7b1b" -dependencies = [ - "memchr", -] - [[package]] name = "quinn" version = "0.11.9" @@ -5151,8 +5416,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls", - "socket2 0.5.10", + "rustls 0.23.35", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -5166,12 +5431,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring", "rustc-hash", - "rustls", + "rustls 0.23.35", "rustls-pki-types", "slab", "thiserror 2.0.17", @@ -5189,16 +5454,16 @@ dependencies = [ "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.1", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -5275,7 +5540,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -5308,10 +5573,24 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.5.15" +name = "rcgen" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.10.0", ] @@ -5329,9 +5608,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.16", "libredox", @@ -5340,22 +5619,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -5367,7 +5646,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.5", + "regex-syntax 0.8.8", ] [[package]] @@ -5378,14 +5657,14 @@ checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax 0.8.8", ] [[package]] name = "regex-lite" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" [[package]] name = "regex-syntax" @@ -5395,27 +5674,27 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.12.24" +version = "0.12.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-channel", "futures-core", "futures-util", - "h2", - "http 1.3.1", - "http-body", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-rustls", "hyper-tls", "hyper-util", @@ -5426,8 +5705,8 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls", - "rustls-native-certs", + "rustls 0.23.35", + "rustls-native-certs 0.8.2", "rustls-pki-types", "serde", "serde_json", @@ -5435,7 +5714,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", - "tokio-rustls", + "tokio-rustls 0.26.4", "tokio-util", "tower", "tower-http", @@ -5469,12 +5748,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b18323edc657390a6ed4d7a9110b0dec2dc3ed128eb2a123edfbafabdbddc5" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", "bytes", "chrono", "futures", - "http 1.3.1", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", "oauth2", "pastey", @@ -5483,7 +5762,7 @@ dependencies = [ "rand 0.9.2", "reqwest", "rmcp-macros", - "schemars 1.0.4", + "schemars 1.1.0", "serde", "serde_json", "sse-stream", @@ -5507,14 +5786,14 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -5531,6 +5810,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom 7.1.3", +] + [[package]] name = "rustix" version = "0.38.44" @@ -5546,37 +5834,61 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.29" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.8", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -5585,10 +5897,19 @@ dependencies = [ ] [[package]] -name = "rustls-pki-types" -version = "1.12.0" +name = "rustls-pemfile" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "web-time", "zeroize", @@ -5596,9 +5917,19 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -5607,9 +5938,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rustyline" @@ -5663,7 +5994,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -5734,14 +6065,14 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" dependencies = [ "chrono", "dyn-clone", "ref-cast", - "schemars_derive 1.0.4", + "schemars_derive 1.1.0", "serde", "serde_json", ] @@ -5755,19 +6086,19 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "schemars_derive" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80" +checksum = "301858a4023d78debd2353c7426dc486001bddc91ae31a76fb1f55132f7e2633" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -5776,6 +6107,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sdd" version = "3.0.10" @@ -6000,7 +6341,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6011,7 +6352,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6020,7 +6361,7 @@ version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.12.0", + "indexmap 2.12.1", "itoa", "memchr", "ryu", @@ -6047,16 +6388,16 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -6077,13 +6418,13 @@ version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.0", + "indexmap 2.12.1", "schemars 0.9.0", - "schemars 1.0.4", + "schemars 1.1.0", "serde_core", "serde_json", "serde_with_macros", @@ -6099,7 +6440,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6108,7 +6449,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.12.0", + "indexmap 2.12.1", "itoa", "ryu", "serde", @@ -6117,9 +6458,9 @@ dependencies = [ [[package]] name = "serial2" -version = "0.2.31" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26e1e5956803a69ddd72ce2de337b577898801528749565def03515f82bad5bb" +checksum = "8cc76fa68e25e771492ca1e3c53d447ef0be3093e05cd3b47f4b712ba10c6f3c" dependencies = [ "cfg-if", "libc", @@ -6148,7 +6489,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6200,9 +6541,9 @@ dependencies = [ [[package]] name = "shell-words" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" [[package]] name = "shlex" @@ -6222,9 +6563,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -6233,18 +6574,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simdutf8" @@ -6310,16 +6651,16 @@ checksum = "eb4dc4d33c68ec1f27d386b5610a351922656e1fdf5c05bbaad930cd1519479a" dependencies = [ "bytes", "futures-util", - "http-body", + "http-body 1.0.1", "http-body-util", "pin-project-lite", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "starlark" @@ -6370,7 +6711,7 @@ dependencies = [ "dupe", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6472,7 +6813,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6484,7 +6825,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6525,9 +6866,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -6551,7 +6892,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6591,10 +6932,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", - "rustix 1.0.8", - "windows-sys 0.61.1", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -6619,12 +6960,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.0.8", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.60.2", ] [[package]] @@ -6651,7 +6992,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6662,15 +7003,15 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "test-case-core", ] [[package]] name = "test-log" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b" +checksum = "37d53ac171c92a39e4769491c4b4dde7022c60042254b5fc044ae409d34a24d4" dependencies = [ "env_logger", "test-log-macros", @@ -6679,13 +7020,13 @@ dependencies = [ [[package]] name = "test-log-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" +checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6734,7 +7075,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6745,7 +7086,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6768,7 +7109,7 @@ dependencies = [ "half", "quick-error", "weezl", - "zune-jpeg 0.4.19", + "zune-jpeg 0.4.21", ] [[package]] @@ -6827,11 +7168,12 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] @@ -6852,33 +7194,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2 0.6.1", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -6893,11 +7232,21 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls 0.23.35", "tokio", ] @@ -6928,9 +7277,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -6952,12 +7301,12 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.5" +version = "0.9.9+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "eb5238e643fc34a1d5d7e753e1532a91912d74b63b92b3ea51fde8d1b7bc79dd" dependencies = [ - "indexmap 2.12.0", - "serde", + "indexmap 2.12.1", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -6967,20 +7316,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.3" +version = "0.7.4+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "fe3cea6b2aa3b910092f6abd4053ea464fab5f9c170ba5e9a6aead16ec4af2b6" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.7" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.0", + "indexmap 2.12.1", "toml_datetime", "toml_parser", "toml_writer", @@ -6989,18 +7338,18 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.0.5+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "4c03bee5ce3696f31250db0bbaff18bc43301ce0e8db2ed1f07cbb2acf89984c" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.4" +version = "1.0.5+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" +checksum = "a9cd6190959dce0994aa8970cd32ab116d1851ead27e866039acaf2524ce44fa" [[package]] name = "tonic" @@ -7010,22 +7359,22 @@ checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ "async-trait", "axum", - "base64", + "base64 0.22.1", "bytes", - "h2", - "http 1.3.1", - "http-body", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "prost", - "rustls-native-certs", + "rustls-native-certs 0.8.2", "socket2 0.5.10", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tokio-stream", "tower", "tower-layer", @@ -7041,7 +7390,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.0", + "indexmap 2.12.1", "pin-project-lite", "slab", "sync_wrapper", @@ -7054,15 +7403,15 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags 2.10.0", "bytes", "futures-util", - "http 1.3.1", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -7096,12 +7445,12 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" dependencies = [ "crossbeam-channel", - "thiserror 1.0.69", + "thiserror 2.0.17", "time", "tracing-subscriber", ] @@ -7114,7 +7463,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -7168,9 +7517,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", @@ -7202,7 +7551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -7213,7 +7562,7 @@ checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" dependencies = [ "cc", "regex", - "regex-syntax 0.8.5", + "regex-syntax 0.8.8", "serde_json", "streaming-iterator", "tree-sitter-language", @@ -7221,9 +7570,9 @@ dependencies = [ [[package]] name = "tree-sitter-bash" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871b0606e667e98a1237ebdc1b0d7056e0aebfdc3141d12b399865d4cb6ed8a6" +checksum = "9e5ec769279cc91b561d3df0d8a5deb26b0ad40d183127f409494d6d8fc53062" dependencies = [ "cc", "tree-sitter-language", @@ -7243,20 +7592,19 @@ dependencies = [ [[package]] name = "tree-sitter-language" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" +checksum = "4ae62f7eae5eb549c71b76658648b72cc6111f2d87d24a1e31fa907f4943e3ce" [[package]] name = "tree_magic_mini" -version = "3.2.0" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f943391d896cdfe8eec03a04d7110332d445be7df856db382dd96a730667562c" +checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6" dependencies = [ "memchr", - "nom", - "once_cell", - "petgraph", + "nom 8.0.0", + "petgraph 0.8.3", ] [[package]] @@ -7267,9 +7615,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ts-rs" -version = "11.0.1" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef1b7a6d914a34127ed8e1fa927eb7088903787bcded4fa3eef8f85ee1568be" +checksum = "4994acea2522cd2b3b85c1d9529a55991e3ad5e25cdcd3de9d505972c4379424" dependencies = [ "serde_json", "thiserror 2.0.17", @@ -7279,21 +7627,21 @@ dependencies = [ [[package]] name = "ts-rs-macros" -version = "11.0.1" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d4ed7b4c18cc150a6a0a1e9ea1ecfa688791220781af6e119f9599a8502a0a" +checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "termcolor", ] [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uds_windows" @@ -7323,9 +7671,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -7386,7 +7734,7 @@ version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" dependencies = [ - "base64", + "base64 0.22.1", "der", "log", "native-tls", @@ -7403,17 +7751,17 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" dependencies = [ - "base64", - "http 1.3.1", + "base64 0.22.1", + "http 1.4.0", "httparse", "log", ] [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -7447,13 +7795,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", - "serde", + "serde_core", "sha1_smol", "wasm-bindgen", ] @@ -7532,45 +7880,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -7581,9 +7916,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7591,22 +7926,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.104", - "wasm-bindgen-backend", + "syn 2.0.111", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] @@ -7632,7 +7967,7 @@ checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ "cc", "downcast-rs", - "rustix 1.0.8", + "rustix 1.1.2", "smallvec", "wayland-sys", ] @@ -7644,7 +7979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ "bitflags 2.10.0", - "rustix 1.0.8", + "rustix 1.1.2", "wayland-backend", "wayland-scanner", ] @@ -7681,7 +8016,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" dependencies = [ "proc-macro2", - "quick-xml 0.37.5", + "quick-xml", "quote", ] @@ -7696,9 +8031,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -7741,18 +8076,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] [[package]] name = "weezl" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "which" @@ -7790,11 +8125,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7854,13 +8189,26 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", + "windows-implement 0.60.2", + "windows-interface 0.59.3", "windows-link 0.1.3", "windows-result 0.3.4", "windows-strings 0.4.2", ] +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-future" version = "0.2.1" @@ -7880,18 +8228,18 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -7902,18 +8250,18 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -7924,9 +8272,9 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-numerics" @@ -7940,13 +8288,13 @@ dependencies = [ [[package]] name = "windows-registry" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -7967,6 +8315,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-strings" version = "0.1.0" @@ -7986,6 +8343,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -8019,16 +8385,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -8046,21 +8412,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -8079,18 +8430,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -8108,12 +8460,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -8122,9 +8468,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -8132,12 +8478,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -8146,9 +8486,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -8156,12 +8496,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -8170,9 +8504,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -8182,9 +8516,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -8192,12 +8526,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -8206,9 +8534,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -8216,12 +8544,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -8230,9 +8552,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -8240,12 +8562,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -8254,9 +8570,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -8264,12 +8580,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -8278,15 +8588,15 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] @@ -8322,12 +8632,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" dependencies = [ "assert-json-diff", - "base64", + "base64 0.22.1", "deadpool", "futures", - "http 1.3.1", + "http 1.4.0", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-util", "log", "once_cell", @@ -8339,25 +8649,21 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.10.0", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wl-clipboard-rs" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5ff8d0e60065f549fafd9d6cb626203ea64a798186c80d8e7df4f8af56baeb" +checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3" dependencies = [ "libc", "log", "os_pipe", - "rustix 0.38.44", - "tempfile", + "rustix 1.1.2", "thiserror 2.0.17", "tree_magic_mini", "wayland-backend", @@ -8374,20 +8680,38 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x11rb" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "gethostname", - "rustix 0.38.44", + "rustix 1.1.2", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] [[package]] name = "xdg-home" @@ -8406,12 +8730,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] -name = "yoke" -version = "0.8.0" +name = "yasna" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -8419,13 +8751,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "synstructure", ] @@ -8476,7 +8808,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "zvariant_utils", ] @@ -8493,22 +8825,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -8528,7 +8860,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "synstructure", ] @@ -8549,14 +8881,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -8577,13 +8909,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] [[package]] @@ -8600,18 +8932,18 @@ checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" [[package]] name = "zune-jpeg" -version = "0.4.19" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ "zune-core 0.4.12", ] [[package]] name = "zune-jpeg" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6fb7703e32e9a07fb3f757360338b3a567a5054f21b5f52a666752e333d58e" +checksum = "51d915729b0e7d5fe35c2f294c5dc10b30207cc637920e5b59077bfa3da63f28" dependencies = [ "zune-core 0.5.0", ] @@ -8638,7 +8970,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", "zvariant_utils", ] @@ -8650,5 +8982,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.111", ] diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 929f74d070..4abf919198 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -26,6 +26,7 @@ members = [ "login", "mcp-server", "mcp-types", + "network-proxy", "ollama", "process-hardening", "protocol", @@ -83,6 +84,7 @@ codex-lmstudio = { path = "lmstudio" } codex-login = { path = "login" } codex-mcp-server = { path = "mcp-server" } codex-ollama = { path = "ollama" } +codex-network-proxy = { path = "network-proxy" } codex-otel = { path = "otel" } codex-process-hardening = { path = "process-hardening" } codex-protocol = { path = "protocol" } @@ -135,6 +137,7 @@ env_logger = "0.11.5" escargot = "0.5" eventsource-stream = "0.2.3" futures = { version = "0.3", default-features = false } +globset = "0.4" http = "1.3.1" icu_decimal = "2.1" icu_locale_core = "2.1" diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 9a1ad16e94..dae8a9575b 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -1346,6 +1346,12 @@ pub fn find_codex_home() -> std::io::Result { Ok(p) } +/// Returns the default path to the Codex config file (`config.toml`). +pub fn default_config_path() -> std::io::Result { + let codex_home = find_codex_home()?; + Ok(codex_home.join(CONFIG_TOML_FILE)) +} + /// Returns the path to the folder where Codex logs are stored. Does not verify /// that the directory exists. pub fn log_dir(cfg: &Config) -> std::io::Result { diff --git a/codex-rs/network-proxy/Cargo.toml b/codex-rs/network-proxy/Cargo.toml new file mode 100644 index 0000000000..89f030d5e2 --- /dev/null +++ b/codex-rs/network-proxy/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "codex-network-proxy" +edition = "2024" +version = { workspace = true } + +[[bin]] +name = "codex-network-proxy" +path = "src/main.rs" + +[lib] +name = "codex_network_proxy" +path = "src/lib.rs" + +[lints] +workspace = true + +[features] +default = ["mitm"] +mitm = [ + "tokio-rustls", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rcgen", +] + +[dependencies] +anyhow = { workspace = true } +clap = { workspace = true, features = ["derive"] } +codex-core = { workspace = true } +globset = { workspace = true } +hyper = { version = "0.14", features = ["full"] } +rcgen = { version = "0.13", features = ["pem", "x509-parser"], optional = true } +rustls = { version = "0.21", optional = true } +rustls-native-certs = { version = "0.6", optional = true } +rustls-pemfile = { version = "1", optional = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +tokio = { workspace = true, features = ["full"] } +tokio-rustls = { version = "0.24", optional = true } +toml = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["fmt"] } diff --git a/codex-rs/network-proxy/src/admin.rs b/codex-rs/network-proxy/src/admin.rs new file mode 100644 index 0000000000..0c9bb4a445 --- /dev/null +++ b/codex-rs/network-proxy/src/admin.rs @@ -0,0 +1,108 @@ +use crate::config::NetworkMode; +use crate::responses::json_response; +use crate::responses::text_response; +use crate::state::AppState; +use anyhow::Result; +use hyper::Body; +use hyper::Method; +use hyper::Request; +use hyper::Response; +use hyper::Server; +use hyper::StatusCode; +use hyper::body::to_bytes; +use hyper::service::make_service_fn; +use hyper::service::service_fn; +use serde::Deserialize; +use serde_json::json; +use std::convert::Infallible; +use std::net::SocketAddr; +use std::sync::Arc; +use tracing::error; +use tracing::info; + +pub async fn run_admin_api(state: Arc, addr: SocketAddr) -> Result<()> { + let make_svc = make_service_fn(move |_conn: &hyper::server::conn::AddrStream| { + let state = state.clone(); + async move { + Ok::<_, Infallible>(service_fn(move |req| { + handle_admin_request(req, state.clone()) + })) + } + }); + let server = Server::bind(&addr).serve(make_svc); + info!(addr = %addr, "admin API listening"); + server.await?; + Ok(()) +} + +async fn handle_admin_request( + req: Request, + state: Arc, +) -> Result, Infallible> { + let method = req.method().clone(); + let path = req.uri().path().to_string(); + let response = match (method, path.as_str()) { + (Method::GET, "/health") => Response::new(Body::from("ok")), + (Method::GET, "/config") => match state.current_cfg().await { + Ok(cfg) => json_response(&cfg), + Err(err) => { + error!(error = %err, "failed to load config"); + text_response(StatusCode::INTERNAL_SERVER_ERROR, "error") + } + }, + (Method::GET, "/patterns") => match state.current_patterns().await { + Ok((allow, deny)) => json_response(&json!({"allowed": allow, "denied": deny})), + Err(err) => { + error!(error = %err, "failed to load patterns"); + text_response(StatusCode::INTERNAL_SERVER_ERROR, "error") + } + }, + (Method::GET, "/blocked") => match state.drain_blocked().await { + Ok(blocked) => json_response(&json!({ "blocked": blocked })), + Err(err) => { + error!(error = %err, "failed to read blocked queue"); + text_response(StatusCode::INTERNAL_SERVER_ERROR, "error") + } + }, + (Method::POST, "/mode") => { + let body = match to_bytes(req.into_body()).await { + Ok(bytes) => bytes, + Err(err) => { + error!(error = %err, "failed to read mode body"); + return Ok(text_response(StatusCode::BAD_REQUEST, "invalid body")); + } + }; + if body.is_empty() { + return Ok(text_response(StatusCode::BAD_REQUEST, "missing body")); + } + let update: ModeUpdate = match serde_json::from_slice(&body) { + Ok(update) => update, + Err(err) => { + error!(error = %err, "failed to parse mode update"); + return Ok(text_response(StatusCode::BAD_REQUEST, "invalid json")); + } + }; + match state.set_network_mode(update.mode).await { + Ok(()) => json_response(&json!({"status": "ok", "mode": update.mode})), + Err(err) => { + error!(error = %err, "mode update failed"); + text_response(StatusCode::INTERNAL_SERVER_ERROR, "mode update failed") + } + } + } + (Method::POST, "/reload") => match state.force_reload().await { + Ok(()) => json_response(&json!({"status": "reloaded"})), + Err(err) => { + error!(error = %err, "reload failed"); + text_response(StatusCode::INTERNAL_SERVER_ERROR, "reload failed") + } + }, + _ => text_response(StatusCode::NOT_FOUND, "not found"), + }; + Ok(response) +} + +#[derive(Deserialize)] +struct ModeUpdate { + mode: NetworkMode, +} diff --git a/codex-rs/network-proxy/src/config.rs b/codex-rs/network-proxy/src/config.rs new file mode 100644 index 0000000000..200c544e98 --- /dev/null +++ b/codex-rs/network-proxy/src/config.rs @@ -0,0 +1,203 @@ +use anyhow::Context; +use anyhow::Result; +use codex_core::config::default_config_path; +use serde::Deserialize; +use serde::Serialize; +use std::net::IpAddr; +use std::net::SocketAddr; +use std::path::PathBuf; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Config { + #[serde(default)] + pub network_proxy: NetworkProxyConfig, +} + +impl Default for Config { + fn default() -> Self { + Self { + network_proxy: NetworkProxyConfig::default(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NetworkProxyConfig { + #[serde(default)] + pub enabled: bool, + #[serde(default = "default_proxy_url")] + pub proxy_url: String, + #[serde(default = "default_admin_url")] + pub admin_url: String, + #[serde(default)] + pub mode: NetworkMode, + #[serde(default)] + pub policy: NetworkPolicy, + #[serde(default)] + pub mitm: MitmConfig, +} + +impl Default for NetworkProxyConfig { + fn default() -> Self { + Self { + enabled: false, + proxy_url: default_proxy_url(), + admin_url: default_admin_url(), + mode: NetworkMode::default(), + policy: NetworkPolicy::default(), + mitm: MitmConfig::default(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NetworkPolicy { + #[serde(default, rename = "allowed_domains", alias = "allowedDomains")] + pub allowed_domains: Vec, + #[serde(default, rename = "denied_domains", alias = "deniedDomains")] + pub denied_domains: Vec, + #[serde(default, rename = "allow_unix_sockets", alias = "allowUnixSockets")] + pub allow_unix_sockets: Vec, + #[serde(default, rename = "allow_local_binding", alias = "allowLocalBinding")] + pub allow_local_binding: bool, +} + +impl Default for NetworkPolicy { + fn default() -> Self { + Self { + allowed_domains: Vec::new(), + denied_domains: Vec::new(), + allow_unix_sockets: Vec::new(), + allow_local_binding: false, + } + } +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum NetworkMode { + Limited, + Full, +} + +impl Default for NetworkMode { + fn default() -> Self { + NetworkMode::Full + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MitmConfig { + #[serde(default)] + pub enabled: bool, + #[serde(default)] + pub inspect: bool, + #[serde(default = "default_mitm_max_body_bytes")] + pub max_body_bytes: usize, + #[serde(default = "default_ca_cert_path")] + pub ca_cert_path: PathBuf, + #[serde(default = "default_ca_key_path")] + pub ca_key_path: PathBuf, +} + +impl Default for MitmConfig { + fn default() -> Self { + Self { + enabled: false, + inspect: false, + max_body_bytes: default_mitm_max_body_bytes(), + ca_cert_path: default_ca_cert_path(), + ca_key_path: default_ca_key_path(), + } + } +} + +fn default_proxy_url() -> String { + "http://127.0.0.1:3128".to_string() +} + +fn default_admin_url() -> String { + "http://127.0.0.1:8080".to_string() +} + +fn default_ca_cert_path() -> PathBuf { + PathBuf::from("network_proxy/mitm/ca.pem") +} + +fn default_ca_key_path() -> PathBuf { + PathBuf::from("network_proxy/mitm/ca.key") +} + +fn default_mitm_max_body_bytes() -> usize { + 4096 +} + +pub struct RuntimeConfig { + pub http_addr: SocketAddr, + pub socks_addr: SocketAddr, + pub admin_addr: SocketAddr, +} + +pub fn default_codex_config_path() -> Result { + default_config_path().context("failed to resolve Codex config path") +} + +pub fn resolve_runtime(cfg: &Config) -> RuntimeConfig { + let http_addr = resolve_addr(&cfg.network_proxy.proxy_url, 3128); + let admin_addr = resolve_addr(&cfg.network_proxy.admin_url, 8080); + let socks_addr = SocketAddr::from(([127, 0, 0, 1], 8081)); + + RuntimeConfig { + http_addr, + socks_addr, + admin_addr, + } +} + +fn resolve_addr(url: &str, default_port: u16) -> SocketAddr { + let (host, port) = parse_host_port(url, default_port); + let host = if host.eq_ignore_ascii_case("localhost") { + "127.0.0.1" + } else { + host + }; + match host.parse::() { + Ok(ip) => SocketAddr::new(ip, port), + Err(_) => SocketAddr::from(([127, 0, 0, 1], port)), + } +} + +fn parse_host_port(url: &str, default_port: u16) -> (&str, u16) { + let trimmed = url.trim(); + if trimmed.is_empty() { + return ("127.0.0.1", default_port); + } + let without_scheme = trimmed + .split_once("://") + .map(|(_, rest)| rest) + .unwrap_or(trimmed); + let host_port = without_scheme.split('/').next().unwrap_or(without_scheme); + let host_port = host_port + .rsplit_once('@') + .map(|(_, rest)| rest) + .unwrap_or(host_port); + + if host_port.starts_with('[') { + if let Some(end) = host_port.find(']') { + let host = &host_port[1..end]; + let port = host_port[end + 1..] + .strip_prefix(':') + .and_then(|port| port.parse::().ok()) + .unwrap_or(default_port); + return (host, port); + } + } + + if let Some((host, port)) = host_port.rsplit_once(':') { + if let Ok(port) = port.parse::() { + return (host, port); + } + } + + (host_port, default_port) +} diff --git a/codex-rs/network-proxy/src/http_proxy.rs b/codex-rs/network-proxy/src/http_proxy.rs new file mode 100644 index 0000000000..f2d8ce5d57 --- /dev/null +++ b/codex-rs/network-proxy/src/http_proxy.rs @@ -0,0 +1,446 @@ +use crate::config::NetworkMode; +use crate::mitm; +use crate::policy::normalize_host; +use crate::responses::blocked_text; +use crate::responses::json_blocked; +use crate::responses::text_response; +use crate::state::AppState; +use crate::state::BlockedRequest; +use anyhow::Result; +use hyper::Body; +use hyper::Method; +use hyper::Request; +use hyper::Response; +use hyper::Server; +use hyper::StatusCode; +use hyper::Uri; +use hyper::body::to_bytes; +use hyper::header::HOST; +use hyper::header::HeaderName; +use hyper::service::make_service_fn; +use hyper::service::service_fn; +use std::collections::HashSet; +use std::convert::Infallible; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::io::copy_bidirectional; +use tokio::net::TcpStream; +use tracing::error; +use tracing::info; +use tracing::warn; + +pub async fn run_http_proxy(state: Arc, addr: SocketAddr) -> Result<()> { + let make_svc = make_service_fn(move |conn: &hyper::server::conn::AddrStream| { + let state = state.clone(); + let client_addr = conn.remote_addr(); + async move { + Ok::<_, Infallible>(service_fn(move |req| { + handle_proxy_request(req, state.clone(), client_addr) + })) + } + }); + let server = Server::bind(&addr).serve(make_svc); + info!(addr = %addr, "HTTP proxy listening"); + server.await?; + Ok(()) +} + +async fn handle_proxy_request( + req: Request, + state: Arc, + client_addr: SocketAddr, +) -> Result, Infallible> { + let response = if req.method() == Method::CONNECT { + handle_connect(req, state, client_addr).await + } else { + handle_http_forward(req, state, client_addr).await + }; + Ok(response) +} + +async fn handle_connect( + req: Request, + state: Arc, + client_addr: SocketAddr, +) -> Response { + let authority = match req.uri().authority() { + Some(auth) => auth.as_str().to_string(), + None => return text_response(StatusCode::BAD_REQUEST, "missing authority"), + }; + let (authority_host, target_port) = split_authority(&authority); + let host = normalize_host(&authority_host); + if host.is_empty() { + return text_response(StatusCode::BAD_REQUEST, "invalid host"); + } + + match state.host_blocked(&host).await { + Ok((true, reason)) => { + let _ = state + .record_blocked(BlockedRequest::new( + host.clone(), + reason.clone(), + Some(client_addr.to_string()), + Some("CONNECT".to_string()), + None, + "http-connect".to_string(), + )) + .await; + warn!(client = %client_addr, host = %host, reason = %reason, "CONNECT blocked"); + return blocked_text(&reason); + } + Ok((false, _)) => { + info!(client = %client_addr, host = %host, "CONNECT allowed"); + } + Err(err) => { + error!(error = %err, "failed to evaluate host"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + } + + let mode = match state.network_mode().await { + Ok(mode) => mode, + Err(err) => { + error!(error = %err, "failed to read network mode"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + }; + + let mitm_state = match state.mitm_state().await { + Ok(state) => state, + Err(err) => { + error!(error = %err, "failed to load MITM state"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + }; + if mode == NetworkMode::Limited && mitm_state.is_none() { + let _ = state + .record_blocked(BlockedRequest::new( + host.clone(), + "mitm_required".to_string(), + Some(client_addr.to_string()), + Some("CONNECT".to_string()), + Some(NetworkMode::Limited), + "http-connect".to_string(), + )) + .await; + warn!( + client = %client_addr, + host = %host, + mode = "limited", + allowed_methods = "GET, HEAD, OPTIONS", + "CONNECT blocked; MITM required for read-only HTTPS in limited mode" + ); + return blocked_text("mitm_required"); + } + + let on_upgrade = hyper::upgrade::on(req); + tokio::spawn(async move { + match on_upgrade.await { + Ok(upgraded) => { + if let Some(mitm_state) = mitm_state { + info!(client = %client_addr, host = %host, mode = ?mode, "CONNECT MITM enabled"); + if let Err(err) = + mitm::mitm_tunnel(upgraded, &host, target_port, mode, mitm_state).await + { + warn!(error = %err, "MITM tunnel error"); + } + return; + } + let mut upgraded = upgraded; + match TcpStream::connect(&authority).await { + Ok(mut server_stream) => { + if let Err(err) = + copy_bidirectional(&mut upgraded, &mut server_stream).await + { + warn!(error = %err, "tunnel error"); + } + } + Err(err) => { + warn!(error = %err, "failed to connect to upstream"); + } + } + } + Err(err) => warn!(error = %err, "upgrade failed"), + } + }); + + Response::builder() + .status(StatusCode::OK) + .body(Body::empty()) + .unwrap_or_else(|_| Response::new(Body::empty())) +} + +async fn handle_http_forward( + req: Request, + state: Arc, + client_addr: SocketAddr, +) -> Response { + let (parts, body) = req.into_parts(); + let method_allowed = match state.method_allowed(&parts.method).await { + Ok(allowed) => allowed, + Err(err) => { + error!(error = %err, "failed to evaluate method policy"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + }; + let unix_socket = parts + .headers + .get("x-unix-socket") + .and_then(|v| v.to_str().ok()) + .map(|v| v.to_string()); + + if let Some(socket_path) = unix_socket { + if !method_allowed { + warn!( + client = %client_addr, + method = %parts.method, + mode = "limited", + allowed_methods = "GET, HEAD, OPTIONS", + "unix socket blocked by method policy" + ); + return json_blocked("unix-socket", "method_not_allowed"); + } + if !cfg!(target_os = "macos") { + warn!(path = %socket_path, "unix socket proxy unsupported on this platform"); + return text_response(StatusCode::NOT_IMPLEMENTED, "unix sockets unsupported"); + } + match state.is_unix_socket_allowed(&socket_path).await { + Ok(true) => { + info!(client = %client_addr, path = %socket_path, "unix socket allowed"); + match proxy_via_unix_socket(Request::from_parts(parts, body), &socket_path).await { + Ok(resp) => return resp, + Err(err) => { + warn!(error = %err, "unix socket proxy failed"); + return text_response(StatusCode::BAD_GATEWAY, "unix socket proxy failed"); + } + } + } + Ok(false) => { + warn!(client = %client_addr, path = %socket_path, "unix socket blocked"); + return json_blocked("unix-socket", "not_allowed"); + } + Err(err) => { + warn!(error = %err, "unix socket check failed"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + } + } + + let host_header = parts + .headers + .get(HOST) + .and_then(|v| v.to_str().ok()) + .map(|v| v.to_string()) + .or_else(|| parts.uri.authority().map(|a| a.as_str().to_string())); + + let authority = match host_header { + Some(h) => h, + None => return text_response(StatusCode::BAD_REQUEST, "missing host"), + }; + let authority = authority.trim().to_string(); + let host = normalize_host(&authority); + if host.is_empty() { + return text_response(StatusCode::BAD_REQUEST, "invalid host"); + } + + match state.host_blocked(&host).await { + Ok((true, reason)) => { + let _ = state + .record_blocked(BlockedRequest::new( + host.clone(), + reason.clone(), + Some(client_addr.to_string()), + Some(parts.method.to_string()), + None, + "http".to_string(), + )) + .await; + warn!(client = %client_addr, host = %host, reason = %reason, "request blocked"); + return json_blocked(&host, &reason); + } + Ok((false, _)) => {} + Err(err) => { + error!(error = %err, "failed to evaluate host"); + return text_response(StatusCode::INTERNAL_SERVER_ERROR, "error"); + } + } + + if !method_allowed { + let _ = state + .record_blocked(BlockedRequest::new( + host.clone(), + "method_not_allowed".to_string(), + Some(client_addr.to_string()), + Some(parts.method.to_string()), + Some(NetworkMode::Limited), + "http".to_string(), + )) + .await; + warn!( + client = %client_addr, + host = %host, + method = %parts.method, + mode = "limited", + allowed_methods = "GET, HEAD, OPTIONS", + "request blocked by method policy" + ); + return json_blocked(&host, "method_not_allowed"); + } + info!( + client = %client_addr, + host = %host, + method = %parts.method, + "request allowed" + ); + + let uri = match build_forward_uri(&authority, &parts.uri) { + Ok(uri) => uri, + Err(err) => { + warn!(error = %err, "failed to build upstream uri"); + return text_response(StatusCode::BAD_REQUEST, "invalid uri"); + } + }; + + let body_bytes = match to_bytes(body).await { + Ok(bytes) => bytes, + Err(err) => { + warn!(error = %err, "failed to read body"); + return text_response(StatusCode::BAD_GATEWAY, "failed to read body"); + } + }; + + let mut builder = Request::builder() + .method(parts.method) + .uri(uri) + .version(parts.version); + let hop_headers = hop_by_hop_headers(); + for (name, value) in parts.headers.iter() { + let name_str = name.as_str().to_ascii_lowercase(); + if hop_headers.contains(name_str.as_str()) + || name == &HeaderName::from_static("x-unix-socket") + { + continue; + } + builder = builder.header(name, value); + } + + let forwarded_req = match builder.body(Body::from(body_bytes)) { + Ok(req) => req, + Err(err) => { + warn!(error = %err, "failed to build request"); + return text_response(StatusCode::BAD_GATEWAY, "invalid request"); + } + }; + + match state.client.request(forwarded_req).await { + Ok(resp) => filter_response(resp), + Err(err) => { + warn!(error = %err, "upstream request failed"); + text_response(StatusCode::BAD_GATEWAY, "upstream failure") + } + } +} + +fn build_forward_uri(authority: &str, uri: &Uri) -> Result { + let path = path_and_query(uri); + let target = format!("http://{authority}{path}"); + Ok(target.parse()?) +} + +fn filter_response(resp: Response) -> Response { + let mut builder = Response::builder().status(resp.status()); + let hop_headers = hop_by_hop_headers(); + for (name, value) in resp.headers().iter() { + if hop_headers.contains(name.as_str().to_ascii_lowercase().as_str()) { + continue; + } + builder = builder.header(name, value); + } + builder + .body(resp.into_body()) + .unwrap_or_else(|_| Response::new(Body::from("proxy error"))) +} + +fn path_and_query(uri: &Uri) -> String { + uri.path_and_query() + .map(|pq| pq.as_str()) + .unwrap_or("/") + .to_string() +} + +fn hop_by_hop_headers() -> HashSet<&'static str> { + [ + "connection", + "proxy-connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ] + .into_iter() + .collect() +} + +fn split_authority(authority: &str) -> (String, u16) { + if let Some(host) = authority.strip_prefix('[') { + if let Some(end) = host.find(']') { + let hostname = host[..end].to_string(); + let port = host[end + 1..] + .strip_prefix(':') + .and_then(|p| p.parse::().ok()) + .unwrap_or(443); + return (hostname, port); + } + } + let mut parts = authority.splitn(2, ':'); + let host = parts.next().unwrap_or("").to_string(); + let port = parts + .next() + .and_then(|p| p.parse::().ok()) + .unwrap_or(443); + (host, port) +} + +async fn proxy_via_unix_socket(req: Request, socket_path: &str) -> Result> { + #[cfg(target_os = "macos")] + { + use hyper::client::conn::Builder as ConnBuilder; + use tokio::net::UnixStream; + + let path = path_and_query(req.uri()); + let (parts, body) = req.into_parts(); + let body_bytes = to_bytes(body).await?; + let mut builder = Request::builder() + .method(parts.method) + .uri(path) + .version(parts.version); + let hop_headers = hop_by_hop_headers(); + for (name, value) in parts.headers.iter() { + let name_str = name.as_str().to_ascii_lowercase(); + if hop_headers.contains(name_str.as_str()) + || name == &HeaderName::from_static("x-unix-socket") + { + continue; + } + builder = builder.header(name, value); + } + let req = builder.body(Body::from(body_bytes))?; + let stream = UnixStream::connect(socket_path).await?; + let (mut sender, conn) = ConnBuilder::new().handshake(stream).await?; + tokio::spawn(async move { + if let Err(err) = conn.await { + warn!(error = %err, "unix socket connection error"); + } + }); + Ok(sender.send_request(req).await?) + } + #[cfg(not(target_os = "macos"))] + { + let _ = req; + let _ = socket_path; + Err(anyhow::anyhow!("unix sockets not supported")) + } +} diff --git a/codex-rs/network-proxy/src/init.rs b/codex-rs/network-proxy/src/init.rs new file mode 100644 index 0000000000..236e617819 --- /dev/null +++ b/codex-rs/network-proxy/src/init.rs @@ -0,0 +1,17 @@ +use anyhow::Context; +use anyhow::Result; +use codex_core::config::find_codex_home; +use std::fs; + +pub fn run_init() -> Result<()> { + let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?; + let root = codex_home.join("network_proxy"); + let mitm_dir = root.join("mitm"); + + fs::create_dir_all(&root).with_context(|| format!("failed to create {}", root.display()))?; + fs::create_dir_all(&mitm_dir) + .with_context(|| format!("failed to create {}", mitm_dir.display()))?; + + println!("ensured {}", mitm_dir.display()); + Ok(()) +} diff --git a/codex-rs/network-proxy/src/lib.rs b/codex-rs/network-proxy/src/lib.rs new file mode 100644 index 0000000000..baa485b4c0 --- /dev/null +++ b/codex-rs/network-proxy/src/lib.rs @@ -0,0 +1,58 @@ +mod admin; +mod config; +mod http_proxy; +mod init; +mod mitm; +mod policy; +mod responses; +mod socks5; +mod state; + +use crate::state::AppState; +use anyhow::Result; +use clap::Parser; +use clap::Subcommand; +use std::net::SocketAddr; +use std::sync::Arc; +use tracing::warn; + +#[derive(Debug, Clone, Parser)] +#[command(name = "codex-network-proxy", about = "Codex network sandbox proxy")] +pub struct Args { + #[command(subcommand)] + pub command: Option, +} + +#[derive(Debug, Clone, Subcommand)] +pub enum Command { + /// Initialize the Codex network proxy directories (e.g. MITM cert paths). + Init, +} + +pub async fn run_main(args: Args) -> Result<()> { + tracing_subscriber::fmt::init(); + + if let Some(Command::Init) = args.command { + init::run_init()?; + return Ok(()); + } + + if cfg!(not(target_os = "macos")) { + warn!("allowUnixSockets is macOS-only; requests will be rejected on this platform"); + } + + let cfg_path = config::default_codex_config_path()?; + let state = Arc::new(AppState::new(cfg_path).await?); + let runtime = config::resolve_runtime(&state.current_cfg().await?); + + let http_addr: SocketAddr = runtime.http_addr; + let socks_addr: SocketAddr = runtime.socks_addr; + let admin_addr: SocketAddr = runtime.admin_addr; + + let http_task = http_proxy::run_http_proxy(state.clone(), http_addr); + let socks_task = socks5::run_socks5(state.clone(), socks_addr); + let admin_task = admin::run_admin_api(state.clone(), admin_addr); + + tokio::try_join!(http_task, socks_task, admin_task)?; + Ok(()) +} diff --git a/codex-rs/network-proxy/src/main.rs b/codex-rs/network-proxy/src/main.rs new file mode 100644 index 0000000000..faea984c92 --- /dev/null +++ b/codex-rs/network-proxy/src/main.rs @@ -0,0 +1,8 @@ +use anyhow::Result; +use clap::Parser; +use codex_network_proxy::Args; + +#[tokio::main] +async fn main() -> Result<()> { + codex_network_proxy::run_main(Args::parse()).await +} diff --git a/codex-rs/network-proxy/src/mitm.rs b/codex-rs/network-proxy/src/mitm.rs new file mode 100644 index 0000000000..3771b207ff --- /dev/null +++ b/codex-rs/network-proxy/src/mitm.rs @@ -0,0 +1,665 @@ +#[cfg(feature = "mitm")] +mod imp { + use crate::config::MitmConfig; + use crate::config::NetworkMode; + use crate::policy::method_allowed; + use crate::policy::normalize_host; + use crate::responses::text_response; + use anyhow::Context; + use anyhow::Result; + use anyhow::anyhow; + use hyper::Body; + use hyper::Method; + use hyper::Request; + use hyper::Response; + use hyper::StatusCode; + use hyper::Uri; + use hyper::Version; + use hyper::body::HttpBody; + use hyper::header::HOST; + use hyper::server::conn::Http; + use hyper::service::service_fn; + use rcgen::BasicConstraints; + use rcgen::Certificate; + use rcgen::CertificateParams; + use rcgen::DistinguishedName; + use rcgen::DnType; + use rcgen::ExtendedKeyUsagePurpose; + use rcgen::IsCa; + use rcgen::KeyPair; + use rcgen::KeyUsagePurpose; + use rcgen::SanType; + use rustls::Certificate as RustlsCertificate; + use rustls::ClientConfig; + use rustls::PrivateKey; + use rustls::RootCertStore; + use rustls::ServerConfig; + use std::collections::HashSet; + use std::convert::Infallible; + use std::fs; + use std::io::Cursor; + use std::net::IpAddr; + use std::path::Path; + use std::sync::Arc; + use tokio::net::TcpStream; + use tokio_rustls::TlsAcceptor; + use tokio_rustls::TlsConnector; + use tracing::info; + use tracing::warn; + + #[derive(Clone, Copy, Debug)] + enum MitmProtocol { + Http1, + Http2, + } + + struct MitmTarget { + host: String, + port: u16, + } + + impl MitmTarget { + fn authority(&self) -> String { + if self.port == 443 { + self.host.clone() + } else { + format!("{}:{}", self.host, self.port) + } + } + } + + struct RequestLogContext { + host: String, + method: Method, + path: String, + } + + struct ResponseLogContext { + host: String, + method: Method, + path: String, + status: StatusCode, + } + + pub struct MitmState { + ca_key: KeyPair, + ca_cert: Certificate, + client_config: Arc, + inspect: bool, + max_body_bytes: usize, + } + + impl MitmState { + pub fn new(cfg: &MitmConfig) -> Result { + let (ca_cert_pem, ca_key_pem) = load_or_create_ca(cfg)?; + let ca_key = KeyPair::from_pem(&ca_key_pem).context("failed to parse CA key")?; + let ca_params = CertificateParams::from_ca_cert_pem(&ca_cert_pem) + .context("failed to parse CA cert")?; + let ca_cert = ca_params + .self_signed(&ca_key) + .context("failed to reconstruct CA cert")?; + let client_config = build_client_config()?; + + Ok(Self { + ca_key, + ca_cert, + client_config, + inspect: cfg.inspect, + max_body_bytes: cfg.max_body_bytes, + }) + } + + pub fn server_config_for_host(&self, host: &str) -> Result> { + let (certs, key) = issue_host_certificate(host, &self.ca_cert, &self.ca_key)?; + let mut config = ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(certs, key) + .context("failed to build server TLS config")?; + config.alpn_protocols = vec![b"http/1.1".to_vec()]; + Ok(Arc::new(config)) + } + + pub fn client_config(&self) -> Arc { + Arc::clone(&self.client_config) + } + + pub fn inspect_enabled(&self) -> bool { + self.inspect + } + + pub fn max_body_bytes(&self) -> usize { + self.max_body_bytes + } + } + + pub async fn mitm_tunnel( + stream: hyper::upgrade::Upgraded, + host: &str, + port: u16, + mode: NetworkMode, + state: Arc, + ) -> Result<()> { + let server_config = state.server_config_for_host(host)?; + let acceptor = TlsAcceptor::from(server_config); + let tls_stream = acceptor + .accept(stream) + .await + .context("client TLS handshake failed")?; + let protocol = match tls_stream.get_ref().1.alpn_protocol() { + Some(proto) if proto == b"h2" => MitmProtocol::Http2, + _ => MitmProtocol::Http1, + }; + info!( + host = %host, + port = port, + protocol = ?protocol, + mode = ?mode, + inspect = state.inspect_enabled(), + max_body_bytes = state.max_body_bytes(), + "MITM TLS established" + ); + + let target = Arc::new(MitmTarget { + host: host.to_string(), + port, + }); + let service = { + let state = state.clone(); + let target = target.clone(); + service_fn(move |req| handle_mitm_request(req, target.clone(), mode, state.clone())) + }; + + let mut http = Http::new(); + match protocol { + MitmProtocol::Http2 => { + http.http2_only(true); + } + MitmProtocol::Http1 => { + http.http1_only(true); + } + } + http.serve_connection(tls_stream, service) + .await + .context("MITM HTTP handling failed")?; + Ok(()) + } + + async fn handle_mitm_request( + req: Request, + target: Arc, + mode: NetworkMode, + state: Arc, + ) -> Result, Infallible> { + let response = match forward_request(req, target.as_ref(), mode, state.as_ref()).await { + Ok(resp) => resp, + Err(err) => { + warn!(error = %err, host = %target.host, "MITM upstream request failed"); + text_response(StatusCode::BAD_GATEWAY, "mitm upstream error") + } + }; + Ok(response) + } + + async fn forward_request( + req: Request, + target: &MitmTarget, + mode: NetworkMode, + state: &MitmState, + ) -> Result> { + if req.method() == Method::CONNECT { + return Ok(text_response( + StatusCode::METHOD_NOT_ALLOWED, + "CONNECT not supported inside MITM", + )); + } + + let (parts, body) = req.into_parts(); + let request_version = parts.version; + let method = parts.method.clone(); + let inspect = state.inspect_enabled(); + let max_body_bytes = state.max_body_bytes(); + + if let Some(request_host) = extract_request_host(&parts) { + let normalized = normalize_host(&request_host); + if !normalized.is_empty() && normalized != target.host { + warn!( + target = %target.host, + request_host = %normalized, + "MITM host mismatch" + ); + return Ok(text_response(StatusCode::BAD_REQUEST, "host mismatch")); + } + } + + let path = path_and_query(&parts.uri); + let uri = build_origin_form_uri(&path)?; + let authority = target.authority(); + + if !method_allowed(mode, &method) { + warn!( + host = %authority, + method = %method, + path = %path, + mode = ?mode, + allowed_methods = "GET, HEAD, OPTIONS", + "MITM blocked by method policy" + ); + return Ok(text_response(StatusCode::FORBIDDEN, "method not allowed")); + } + + let mut builder = Request::builder() + .method(method.clone()) + .uri(uri) + .version(Version::HTTP_11); + + let hop_headers = hop_by_hop_headers(); + for (name, value) in parts.headers.iter() { + let name_str = name.as_str().to_ascii_lowercase(); + if hop_headers.contains(name_str.as_str()) || name == &HOST { + continue; + } + builder = builder.header(name, value); + } + builder = builder.header(HOST, authority.as_str()); + + let body = if inspect { + let (tx, out_body) = Body::channel(); + let ctx = RequestLogContext { + host: authority.clone(), + method: method.clone(), + path: path.clone(), + }; + tokio::spawn(async move { + stream_body(body, tx, max_body_bytes, ctx).await; + }); + out_body + } else { + body + }; + + let upstream_req = builder + .body(body) + .context("failed to build upstream request")?; + let upstream_resp = send_upstream_request(upstream_req, target, state).await?; + + respond_with_inspection( + upstream_resp, + request_version, + inspect, + max_body_bytes, + &method, + &path, + &authority, + ) + .await + } + + async fn send_upstream_request( + req: Request, + target: &MitmTarget, + state: &MitmState, + ) -> Result> { + let upstream = TcpStream::connect((target.host.as_str(), target.port)) + .await + .context("failed to connect to upstream")?; + let server_name = match target.host.parse::() { + Ok(ip) => rustls::ServerName::IpAddress(ip), + Err(_) => rustls::ServerName::try_from(target.host.as_str()) + .map_err(|_| anyhow!("invalid server name"))?, + }; + let connector = TlsConnector::from(state.client_config()); + let tls_stream = connector + .connect(server_name, upstream) + .await + .context("upstream TLS handshake failed")?; + let (mut sender, conn) = hyper::client::conn::Builder::new() + .handshake(tls_stream) + .await + .context("upstream HTTP handshake failed")?; + tokio::spawn(async move { + if let Err(err) = conn.await { + warn!(error = %err, "MITM upstream connection error"); + } + }); + let resp = sender + .send_request(req) + .await + .context("upstream request failed")?; + Ok(resp) + } + + async fn respond_with_inspection( + resp: Response, + request_version: Version, + inspect: bool, + max_body_bytes: usize, + method: &Method, + path: &str, + authority: &str, + ) -> Result> { + let (parts, body) = resp.into_parts(); + + let mut builder = Response::builder() + .status(parts.status) + .version(request_version); + let hop_headers = hop_by_hop_headers(); + for (name, value) in parts.headers.iter() { + if hop_headers.contains(name.as_str().to_ascii_lowercase().as_str()) { + continue; + } + builder = builder.header(name, value); + } + let body = if inspect { + let (tx, out_body) = Body::channel(); + let ctx = ResponseLogContext { + host: authority.to_string(), + method: method.clone(), + path: path.to_string(), + status: parts.status, + }; + tokio::spawn(async move { + stream_body(body, tx, max_body_bytes, ctx).await; + }); + out_body + } else { + body + }; + Ok(builder + .body(body) + .unwrap_or_else(|_| Response::new(Body::from("proxy error")))) + } + + async fn stream_body( + mut body: Body, + mut tx: hyper::body::Sender, + max_body_bytes: usize, + ctx: T, + ) where + T: BodyLoggable, + { + let mut len: usize = 0; + let mut truncated = false; + while let Some(chunk) = body.data().await { + match chunk { + Ok(bytes) => { + len = len.saturating_add(bytes.len()); + if len > max_body_bytes { + truncated = true; + } + if tx.send_data(bytes).await.is_err() { + break; + } + } + Err(err) => { + warn!(error = %err, "MITM body stream error"); + break; + } + } + } + if let Ok(Some(trailers)) = body.trailers().await { + let _ = tx.send_trailers(trailers).await; + } + ctx.log(len, truncated); + } + + trait BodyLoggable { + fn log(self, len: usize, truncated: bool); + } + + impl BodyLoggable for RequestLogContext { + fn log(self, len: usize, truncated: bool) { + info!( + host = %self.host, + method = %self.method, + path = %self.path, + body_len = len, + truncated = truncated, + "MITM inspected request body" + ); + } + } + + impl BodyLoggable for ResponseLogContext { + fn log(self, len: usize, truncated: bool) { + info!( + host = %self.host, + method = %self.method, + path = %self.path, + status = %self.status, + body_len = len, + truncated = truncated, + "MITM inspected response body" + ); + } + } + + fn extract_request_host(parts: &hyper::http::request::Parts) -> Option { + parts + .headers + .get(HOST) + .and_then(|v| v.to_str().ok()) + .map(|v| v.to_string()) + .or_else(|| parts.uri.authority().map(|a| a.as_str().to_string())) + } + + fn path_and_query(uri: &Uri) -> String { + uri.path_and_query() + .map(|pq| pq.as_str()) + .unwrap_or("/") + .to_string() + } + + fn build_origin_form_uri(path: &str) -> Result { + path.parse().context("invalid request path") + } + + fn hop_by_hop_headers() -> HashSet<&'static str> { + [ + "connection", + "proxy-connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ] + .into_iter() + .collect() + } + + fn build_client_config() -> Result> { + let mut roots = RootCertStore::empty(); + let certs = rustls_native_certs::load_native_certs() + .map_err(|err| anyhow!("failed to load native certs: {err}"))?; + for cert in certs { + if roots.add(&RustlsCertificate(cert.0)).is_err() { + warn!("skipping invalid root cert"); + } + } + if roots.is_empty() { + return Err(anyhow!("no root certificates available")); + } + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(roots) + .with_no_client_auth(); + config.alpn_protocols = vec![b"http/1.1".to_vec()]; + Ok(Arc::new(config)) + } + + fn issue_host_certificate( + host: &str, + ca_cert: &Certificate, + ca_key: &KeyPair, + ) -> Result<(Vec, PrivateKey)> { + let mut params = if let Ok(ip) = host.parse::() { + let mut params = CertificateParams::new(Vec::new()) + .map_err(|err| anyhow!("failed to create cert params: {err}"))?; + params.subject_alt_names.push(SanType::IpAddress(ip)); + params + } else { + CertificateParams::new(vec![host.to_string()]) + .map_err(|err| anyhow!("failed to create cert params: {err}"))? + }; + params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth]; + params.key_usages = vec![ + KeyUsagePurpose::DigitalSignature, + KeyUsagePurpose::KeyEncipherment, + ]; + + let key_pair = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256) + .map_err(|err| anyhow!("failed to generate host key pair: {err}"))?; + let cert = params + .signed_by(&key_pair, ca_cert, ca_key) + .map_err(|err| anyhow!("failed to sign host cert: {err}"))?; + + let cert_pem = cert.pem(); + let key_pem = key_pair.serialize_pem(); + let certs = certs_from_pem(&cert_pem)?; + let key = private_key_from_pem(&key_pem)?; + Ok((certs, key)) + } + + fn load_or_create_ca(cfg: &MitmConfig) -> Result<(String, String)> { + let cert_path = &cfg.ca_cert_path; + let key_path = &cfg.ca_key_path; + if cert_path.exists() || key_path.exists() { + if !cert_path.exists() || !key_path.exists() { + return Err(anyhow!("both ca_cert_path and ca_key_path must exist")); + } + let cert_pem = fs::read_to_string(cert_path) + .with_context(|| format!("failed to read CA cert {}", cert_path.display()))?; + let key_pem = fs::read_to_string(key_path) + .with_context(|| format!("failed to read CA key {}", key_path.display()))?; + return Ok((cert_pem, key_pem)); + } + + if let Some(parent) = cert_path.parent() { + fs::create_dir_all(parent) + .with_context(|| format!("failed to create {}", parent.display()))?; + } + if let Some(parent) = key_path.parent() { + fs::create_dir_all(parent) + .with_context(|| format!("failed to create {}", parent.display()))?; + } + + let (cert_pem, key_pem) = generate_ca()?; + write_private_file(cert_path, cert_pem.as_bytes(), 0o644)?; + write_private_file(key_path, key_pem.as_bytes(), 0o600)?; + info!( + cert_path = %cert_path.display(), + key_path = %key_path.display(), + "generated MITM CA" + ); + Ok((cert_pem, key_pem)) + } + + fn generate_ca() -> Result<(String, String)> { + let mut params = CertificateParams::default(); + params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); + params.key_usages = vec![ + KeyUsagePurpose::KeyCertSign, + KeyUsagePurpose::DigitalSignature, + KeyUsagePurpose::KeyEncipherment, + ]; + let mut dn = DistinguishedName::new(); + dn.push(DnType::CommonName, "network_proxy MITM CA"); + params.distinguished_name = dn; + + let key_pair = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256) + .map_err(|err| anyhow!("failed to generate CA key pair: {err}"))?; + let cert = params + .self_signed(&key_pair) + .map_err(|err| anyhow!("failed to generate CA cert: {err}"))?; + let cert_pem = cert.pem(); + let key_pem = key_pair.serialize_pem(); + Ok((cert_pem, key_pem)) + } + + fn certs_from_pem(pem: &str) -> Result> { + let mut reader = Cursor::new(pem); + let certs = rustls_pemfile::certs(&mut reader).context("failed to parse cert PEM")?; + if certs.is_empty() { + return Err(anyhow!("no certificates found")); + } + Ok(certs.into_iter().map(RustlsCertificate).collect()) + } + + fn private_key_from_pem(pem: &str) -> Result { + let mut reader = Cursor::new(pem); + let mut keys = + rustls_pemfile::pkcs8_private_keys(&mut reader).context("failed to parse pkcs8 key")?; + if let Some(key) = keys.pop() { + return Ok(PrivateKey(key)); + } + let mut reader = Cursor::new(pem); + let mut keys = + rustls_pemfile::rsa_private_keys(&mut reader).context("failed to parse rsa key")?; + if let Some(key) = keys.pop() { + return Ok(PrivateKey(key)); + } + Err(anyhow!("no private key found")) + } + + fn write_private_file(path: &Path, contents: &[u8], mode: u32) -> Result<()> { + fs::write(path, contents).with_context(|| format!("failed to write {}", path.display()))?; + set_permissions(path, mode)?; + Ok(()) + } + + #[cfg(unix)] + fn set_permissions(path: &Path, mode: u32) -> Result<()> { + use std::os::unix::fs::PermissionsExt; + fs::set_permissions(path, fs::Permissions::from_mode(mode)) + .with_context(|| format!("failed to set permissions on {}", path.display()))?; + Ok(()) + } + + #[cfg(not(unix))] + fn set_permissions(_path: &Path, _mode: u32) -> Result<()> { + Ok(()) + } +} + +#[cfg(not(feature = "mitm"))] +mod imp { + use crate::config::MitmConfig; + use crate::config::NetworkMode; + use anyhow::Result; + use anyhow::anyhow; + use hyper::upgrade::Upgraded; + use std::sync::Arc; + + #[derive(Debug)] + pub struct MitmState; + + #[allow(dead_code)] + impl MitmState { + pub fn new(_cfg: &MitmConfig) -> Result { + Err(anyhow!("MITM feature disabled at build time")) + } + + pub fn inspect_enabled(&self) -> bool { + false + } + + pub fn max_body_bytes(&self) -> usize { + 0 + } + } + + pub async fn mitm_tunnel( + _stream: Upgraded, + _host: &str, + _port: u16, + _mode: NetworkMode, + _state: Arc, + ) -> Result<()> { + Err(anyhow!("MITM feature disabled at build time")) + } +} + +pub use imp::*; diff --git a/codex-rs/network-proxy/src/policy.rs b/codex-rs/network-proxy/src/policy.rs new file mode 100644 index 0000000000..684b101013 --- /dev/null +++ b/codex-rs/network-proxy/src/policy.rs @@ -0,0 +1,31 @@ +use crate::config::NetworkMode; +use hyper::Method; +use std::net::IpAddr; + +pub fn method_allowed(mode: NetworkMode, method: &Method) -> bool { + match mode { + NetworkMode::Full => true, + NetworkMode::Limited => matches!(method, &Method::GET | &Method::HEAD | &Method::OPTIONS), + } +} + +pub fn is_loopback_host(host: &str) -> bool { + let host = host.to_ascii_lowercase(); + if host == "localhost" || host == "localhost." { + return true; + } + if let Ok(ip) = host.parse::() { + return ip.is_loopback(); + } + false +} + +pub fn normalize_host(host: &str) -> String { + let host = host.trim(); + if host.starts_with('[') { + if let Some(end) = host.find(']') { + return host[1..end].to_ascii_lowercase(); + } + } + host.split(':').next().unwrap_or("").to_ascii_lowercase() +} diff --git a/codex-rs/network-proxy/src/responses.rs b/codex-rs/network-proxy/src/responses.rs new file mode 100644 index 0000000000..a5007e9054 --- /dev/null +++ b/codex-rs/network-proxy/src/responses.rs @@ -0,0 +1,65 @@ +use hyper::Body; +use hyper::Response; +use hyper::StatusCode; +use serde::Serialize; +use serde_json::json; + +pub fn json_blocked(host: &str, reason: &str) -> Response { + let body = Body::from(json!({"status":"blocked","host":host,"reason":reason}).to_string()); + Response::builder() + .status(StatusCode::FORBIDDEN) + .header("content-type", "application/json") + .header("x-proxy-error", blocked_header_value(reason)) + .body(body) + .unwrap_or_else(|_| Response::new(Body::from("blocked"))) +} + +pub fn blocked_text(reason: &str) -> Response { + Response::builder() + .status(StatusCode::FORBIDDEN) + .header("content-type", "text/plain") + .header("x-proxy-error", blocked_header_value(reason)) + .body(Body::from(blocked_message(reason).to_string())) + .unwrap_or_else(|_| Response::new(Body::from("blocked"))) +} + +pub fn text_response(status: StatusCode, body: &str) -> Response { + Response::builder() + .status(status) + .header("content-type", "text/plain") + .body(Body::from(body.to_string())) + .unwrap_or_else(|_| Response::new(Body::from(body.to_string()))) +} + +pub fn json_response(value: &T) -> Response { + let body = match serde_json::to_string(value) { + Ok(body) => body, + Err(_) => "{}".to_string(), + }; + Response::builder() + .status(StatusCode::OK) + .header("content-type", "application/json") + .body(Body::from(body)) + .unwrap_or_else(|_| Response::new(Body::from("{}"))) +} + +fn blocked_header_value(reason: &str) -> &'static str { + match reason { + "not_allowed" | "not_allowed_local" => "blocked-by-allowlist", + "denied" => "blocked-by-denylist", + "method_not_allowed" => "blocked-by-method-policy", + "mitm_required" => "blocked-by-mitm-required", + _ => "blocked-by-policy", + } +} + +fn blocked_message(reason: &str) -> &'static str { + match reason { + "not_allowed" => "Codex blocked this request: domain not in allowlist.", + "not_allowed_local" => "Codex blocked this request: local addresses not allowed.", + "denied" => "Codex blocked this request: domain denied by policy.", + "method_not_allowed" => "Codex blocked this request: method not allowed in limited mode.", + "mitm_required" => "Codex blocked this request: MITM required for limited HTTPS.", + _ => "Codex blocked this request by network policy.", + } +} diff --git a/codex-rs/network-proxy/src/socks5.rs b/codex-rs/network-proxy/src/socks5.rs new file mode 100644 index 0000000000..65b9680af3 --- /dev/null +++ b/codex-rs/network-proxy/src/socks5.rs @@ -0,0 +1,192 @@ +use crate::config::NetworkMode; +use crate::policy::normalize_host; +use crate::state::AppState; +use crate::state::BlockedRequest; +use anyhow::Result; +use anyhow::anyhow; +use std::net::SocketAddr; +use std::sync::Arc; +use tokio::io::AsyncReadExt; +use tokio::io::AsyncWriteExt; +use tokio::io::copy_bidirectional; +use tokio::net::TcpListener; +use tokio::net::TcpStream; +use tracing::error; +use tracing::info; +use tracing::warn; + +pub async fn run_socks5(state: Arc, addr: SocketAddr) -> Result<()> { + let listener = TcpListener::bind(addr).await?; + info!(addr = %addr, "SOCKS5 proxy listening"); + match state.network_mode().await { + Ok(NetworkMode::Limited) => { + info!( + mode = "limited", + "SOCKS5 is blocked in limited mode; set mode=\"full\" to allow SOCKS5" + ); + } + Ok(NetworkMode::Full) => {} + Err(err) => { + warn!(error = %err, "failed to read network mode"); + } + } + loop { + let (stream, peer_addr) = listener.accept().await?; + let state = state.clone(); + tokio::spawn(async move { + if let Err(err) = handle_socks5_client(stream, peer_addr, state).await { + warn!(error = %err, "SOCKS5 session ended with error"); + } + }); + } +} + +async fn handle_socks5_client( + mut stream: TcpStream, + peer_addr: SocketAddr, + state: Arc, +) -> Result<()> { + let mut header = [0u8; 2]; + stream.read_exact(&mut header).await?; + if header[0] != 0x05 { + return Err(anyhow!("invalid SOCKS version")); + } + let nmethods = header[1] as usize; + let mut methods = vec![0u8; nmethods]; + stream.read_exact(&mut methods).await?; + stream.write_all(&[0x05, 0x00]).await?; + + let mut req_header = [0u8; 4]; + stream.read_exact(&mut req_header).await?; + if req_header[0] != 0x05 { + return Err(anyhow!("invalid SOCKS request version")); + } + let cmd = req_header[1]; + if cmd != 0x01 { + stream + .write_all(&[0x05, 0x07, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Err(anyhow!("unsupported SOCKS command")); + } + let atyp = req_header[3]; + let host = match atyp { + 0x01 => { + let mut addr = [0u8; 4]; + stream.read_exact(&mut addr).await?; + format!("{}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]) + } + 0x03 => { + let mut len_buf = [0u8; 1]; + stream.read_exact(&mut len_buf).await?; + let len = len_buf[0] as usize; + let mut domain = vec![0u8; len]; + stream.read_exact(&mut domain).await?; + String::from_utf8_lossy(&domain).to_string() + } + 0x04 => { + stream + .write_all(&[0x05, 0x08, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Err(anyhow!("ipv6 not supported")); + } + _ => { + stream + .write_all(&[0x05, 0x08, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Err(anyhow!("unknown address type")); + } + }; + + let mut port_buf = [0u8; 2]; + stream.read_exact(&mut port_buf).await?; + let port = u16::from_be_bytes(port_buf); + let normalized_host = normalize_host(&host); + + match state.network_mode().await { + Ok(NetworkMode::Limited) => { + let _ = state + .record_blocked(BlockedRequest::new( + normalized_host.clone(), + "method_not_allowed".to_string(), + Some(peer_addr.to_string()), + None, + Some(NetworkMode::Limited), + "socks5".to_string(), + )) + .await; + warn!( + client = %peer_addr, + host = %normalized_host, + mode = "limited", + allowed_methods = "GET, HEAD, OPTIONS", + "SOCKS blocked by method policy" + ); + stream + .write_all(&[0x05, 0x02, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Ok(()); + } + Ok(NetworkMode::Full) => {} + Err(err) => { + error!(error = %err, "failed to evaluate method policy"); + stream + .write_all(&[0x05, 0x01, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Ok(()); + } + } + + match state.host_blocked(&normalized_host).await { + Ok((true, reason)) => { + let _ = state + .record_blocked(BlockedRequest::new( + normalized_host.clone(), + reason.clone(), + Some(peer_addr.to_string()), + None, + None, + "socks5".to_string(), + )) + .await; + warn!(client = %peer_addr, host = %normalized_host, reason = %reason, "SOCKS blocked"); + stream + .write_all(&[0x05, 0x02, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Ok(()); + } + Ok((false, _)) => { + info!( + client = %peer_addr, + host = %normalized_host, + port = port, + "SOCKS allowed" + ); + } + Err(err) => { + error!(error = %err, "failed to evaluate host"); + stream + .write_all(&[0x05, 0x01, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Ok(()); + } + } + + let target = format!("{host}:{port}"); + let mut upstream = match TcpStream::connect(&target).await { + Ok(stream) => stream, + Err(err) => { + warn!(error = %err, "SOCKS connect failed"); + stream + .write_all(&[0x05, 0x04, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + return Ok(()); + } + }; + + stream + .write_all(&[0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0]) + .await?; + + let _ = copy_bidirectional(&mut stream, &mut upstream).await; + Ok(()) +} diff --git a/codex-rs/network-proxy/src/state.rs b/codex-rs/network-proxy/src/state.rs new file mode 100644 index 0000000000..d196065a27 --- /dev/null +++ b/codex-rs/network-proxy/src/state.rs @@ -0,0 +1,350 @@ +use crate::config::Config; +use crate::config::MitmConfig; +use crate::config::NetworkMode; +use crate::mitm::MitmState; +use crate::policy::is_loopback_host; +use crate::policy::method_allowed; +use anyhow::Context; +use anyhow::Result; +use anyhow::anyhow; +use globset::GlobBuilder; +use globset::GlobSet; +use globset::GlobSetBuilder; +use hyper::Client; +use hyper::Method; +use hyper::client::HttpConnector; +use serde::Serialize; +use std::collections::HashSet; +use std::collections::VecDeque; +use std::path::Path; +use std::path::PathBuf; +use std::sync::Arc; +use std::time::SystemTime; +use std::time::UNIX_EPOCH; +use tokio::sync::RwLock; +use tracing::info; +use tracing::warn; + +const MAX_BLOCKED_EVENTS: usize = 200; + +#[derive(Clone, Debug, Serialize)] +pub struct BlockedRequest { + pub host: String, + pub reason: String, + pub client: Option, + pub method: Option, + pub mode: Option, + pub protocol: String, + pub timestamp: i64, +} + +impl BlockedRequest { + pub fn new( + host: String, + reason: String, + client: Option, + method: Option, + mode: Option, + protocol: String, + ) -> Self { + Self { + host, + reason, + client, + method, + mode, + protocol, + timestamp: unix_timestamp(), + } + } +} + +#[derive(Clone)] +struct ConfigState { + cfg: Config, + mtime: Option, + allow_set: GlobSet, + deny_set: GlobSet, + mitm: Option>, + cfg_path: PathBuf, + blocked: VecDeque, +} + +#[derive(Clone)] +pub struct AppState { + pub(crate) client: Client, + state: Arc>, +} + +impl AppState { + pub async fn new(cfg_path: PathBuf) -> Result { + let cfg_state = build_config_state(cfg_path)?; + let client = Client::new(); + Ok(Self { + client, + state: Arc::new(RwLock::new(cfg_state)), + }) + } + + pub async fn current_cfg(&self) -> Result { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(guard.cfg.clone()) + } + + pub async fn current_patterns(&self) -> Result<(Vec, Vec)> { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(( + guard.cfg.network_proxy.policy.allowed_domains.clone(), + guard.cfg.network_proxy.policy.denied_domains.clone(), + )) + } + + pub async fn force_reload(&self) -> Result<()> { + let mut guard = self.state.write().await; + let previous_cfg = guard.cfg.clone(); + let blocked = guard.blocked.clone(); + let cfg_path = guard.cfg_path.clone(); + match build_config_state(cfg_path.clone()) { + Ok(mut new_state) => { + log_policy_changes(&previous_cfg, &new_state.cfg); + new_state.blocked = blocked; + *guard = new_state; + info!(path = %cfg_path.display(), "reloaded config"); + Ok(()) + } + Err(err) => { + warn!(error = %err, path = %cfg_path.display(), "failed to reload config; keeping previous config"); + Err(err) + } + } + } + + pub async fn host_blocked(&self, host: &str) -> Result<(bool, String)> { + self.reload_if_needed().await?; + let guard = self.state.read().await; + if guard.deny_set.is_match(host) { + return Ok((true, "denied".to_string())); + } + let is_loopback = is_loopback_host(host); + if is_loopback + && !guard.cfg.network_proxy.policy.allow_local_binding + && !guard.allow_set.is_match(host) + { + return Ok((true, "not_allowed_local".to_string())); + } + if guard.cfg.network_proxy.policy.allowed_domains.is_empty() + || !guard.allow_set.is_match(host) + { + return Ok((true, "not_allowed".to_string())); + } + Ok((false, String::new())) + } + + pub async fn record_blocked(&self, entry: BlockedRequest) -> Result<()> { + self.reload_if_needed().await?; + let mut guard = self.state.write().await; + guard.blocked.push_back(entry); + while guard.blocked.len() > MAX_BLOCKED_EVENTS { + guard.blocked.pop_front(); + } + Ok(()) + } + + pub async fn drain_blocked(&self) -> Result> { + self.reload_if_needed().await?; + let mut guard = self.state.write().await; + let blocked = std::mem::take(&mut guard.blocked); + Ok(blocked.into_iter().collect()) + } + + pub async fn is_unix_socket_allowed(&self, path: &str) -> Result { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(guard + .cfg + .network_proxy + .policy + .allow_unix_sockets + .iter() + .any(|p| p == path)) + } + + pub async fn method_allowed(&self, method: &Method) -> Result { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(method_allowed(guard.cfg.network_proxy.mode, method)) + } + + pub async fn network_mode(&self) -> Result { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(guard.cfg.network_proxy.mode) + } + + pub async fn set_network_mode(&self, mode: NetworkMode) -> Result<()> { + self.reload_if_needed().await?; + let mut guard = self.state.write().await; + guard.cfg.network_proxy.mode = mode; + info!(mode = ?mode, "updated network mode"); + Ok(()) + } + + pub async fn mitm_state(&self) -> Result>> { + self.reload_if_needed().await?; + let guard = self.state.read().await; + Ok(guard.mitm.clone()) + } + + async fn reload_if_needed(&self) -> Result<()> { + let needs_reload = { + let guard = self.state.read().await; + if !guard.cfg_path.exists() { + true + } else { + let metadata = std::fs::metadata(&guard.cfg_path).ok(); + match (metadata.and_then(|m| m.modified().ok()), guard.mtime) { + (Some(new_mtime), Some(old_mtime)) => new_mtime > old_mtime, + (Some(_), None) => true, + _ => false, + } + } + }; + + if !needs_reload { + return Ok(()); + } + + self.force_reload().await + } +} + +fn build_config_state(cfg_path: PathBuf) -> Result { + let mut cfg = if cfg_path.exists() { + load_config_from_path(&cfg_path).with_context(|| { + format!( + "failed to load config from {}", + cfg_path.as_path().display() + ) + })? + } else { + Config::default() + }; + resolve_mitm_paths(&mut cfg, &cfg_path); + let mtime = cfg_path.metadata().and_then(|m| m.modified()).ok(); + let deny_set = compile_globset(&cfg.network_proxy.policy.denied_domains)?; + let allow_set = compile_globset(&cfg.network_proxy.policy.allowed_domains)?; + let mitm = if cfg.network_proxy.mitm.enabled { + build_mitm_state(&cfg.network_proxy.mitm)? + } else { + None + }; + Ok(ConfigState { + cfg, + mtime, + allow_set, + deny_set, + mitm, + cfg_path, + blocked: VecDeque::new(), + }) +} + +fn resolve_mitm_paths(cfg: &mut Config, cfg_path: &Path) { + let base = cfg_path.parent().unwrap_or_else(|| Path::new(".")); + if cfg.network_proxy.mitm.ca_cert_path.is_relative() { + cfg.network_proxy.mitm.ca_cert_path = base.join(&cfg.network_proxy.mitm.ca_cert_path); + } + if cfg.network_proxy.mitm.ca_key_path.is_relative() { + cfg.network_proxy.mitm.ca_key_path = base.join(&cfg.network_proxy.mitm.ca_key_path); + } +} + +fn build_mitm_state(_cfg: &MitmConfig) -> Result>> { + #[cfg(feature = "mitm")] + { + return Ok(Some(Arc::new(MitmState::new(_cfg)?))); + } + #[cfg(not(feature = "mitm"))] + { + warn!("MITM enabled in config but binary built without mitm feature"); + Ok(None) + } +} + +fn compile_globset(patterns: &[String]) -> Result { + let mut builder = GlobSetBuilder::new(); + let mut seen = HashSet::new(); + for pattern in patterns { + let mut expanded = Vec::with_capacity(2); + expanded.push(pattern.as_str()); + if let Some(apex) = pattern.strip_prefix("*.") { + expanded.push(apex); + } + for candidate in expanded { + if !seen.insert(candidate.to_string()) { + continue; + } + let glob = GlobBuilder::new(candidate) + .case_insensitive(true) + .build() + .with_context(|| format!("invalid glob pattern: {candidate}"))?; + builder.add(glob); + } + } + Ok(builder.build()?) +} + +fn log_policy_changes(previous: &Config, next: &Config) { + log_domain_list_changes( + "allowlist", + &previous.network_proxy.policy.allowed_domains, + &next.network_proxy.policy.allowed_domains, + ); + log_domain_list_changes( + "denylist", + &previous.network_proxy.policy.denied_domains, + &next.network_proxy.policy.denied_domains, + ); +} + +fn log_domain_list_changes(list_name: &str, previous: &[String], next: &[String]) { + let previous_set: HashSet = previous + .iter() + .map(|entry| entry.to_ascii_lowercase()) + .collect(); + let next_set: HashSet = next + .iter() + .map(|entry| entry.to_ascii_lowercase()) + .collect(); + + let mut seen_next = HashSet::new(); + for entry in next { + let key = entry.to_ascii_lowercase(); + if seen_next.insert(key.clone()) && !previous_set.contains(&key) { + info!(list = list_name, entry = %entry, "config entry added"); + } + } + + let mut seen_previous = HashSet::new(); + for entry in previous { + let key = entry.to_ascii_lowercase(); + if seen_previous.insert(key.clone()) && !next_set.contains(&key) { + info!(list = list_name, entry = %entry, "config entry removed"); + } + } +} + +fn unix_timestamp() -> i64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|duration| duration.as_secs() as i64) + .unwrap_or(0) +} + +fn load_config_from_path(path: &Path) -> Result { + let raw = std::fs::read_to_string(path) + .with_context(|| format!("unable to read config file {}", path.display()))?; + toml::from_str(&raw).map_err(|err| anyhow!("unable to parse config: {err}")) +} diff --git a/docs/network-proxy-design.md b/docs/network-proxy-design.md new file mode 100644 index 0000000000..7cc7489b6a --- /dev/null +++ b/docs/network-proxy-design.md @@ -0,0 +1,102 @@ +# Codex Network Proxy Design + +This document describes the Codex network proxy that runs outside the sandbox and enforces an allow-only network policy for sandboxed subprocesses. The proxy is a single binary with HTTP proxying, SOCKS5, and an admin API. Codex owns the policy state in `~/.codex/config.toml`; the proxy reads that configuration and applies it at the network edge. + +## Goals + +1. Enforce allow-only network access with denylist precedence. +2. Support wildcard domain patterns, including apex match for `*.domain.tld`. +3. Allow two modes: **limited** (read-only) and **full** (all methods). +4. Provide optional **MITM** to enforce read-only on HTTPS. +5. Allow hot-reloaded configuration via admin API. +6. Provide clear audit logging of allow/deny decisions and policy changes. +7. Enable a single binary with HTTP proxy, SOCKS5 proxy, and admin API. + +## Non-Goals + +- Enterprise policy distribution or centralized multi-tenant orchestration. +- Deep packet inspection beyond the supported HTTP/HTTPS interception modes. +- Perfect protocol coverage for all network traffic types. + +## Architecture + +```mermaid +flowchart LR + subgraph Sandbox["Codex (sandboxed)"] + Tools["commands / tools
curl, git, python"] + SocksClients["SOCKS clients"] + end + + subgraph Proxy["codex-network-proxy (host process)"] + HttpProxy["HTTP Proxy :3128
CONNECT tunnel
MITM (optional)"] + SocksProxy["SOCKS5 Proxy :8081"] + Admin["Admin API :8080
/health /config /blocked
/reload /mode"] + end + + Config["~/.codex/config.toml
[network_proxy.*]"] + + Tools -->|HTTP| HttpProxy + SocksClients -->|SOCKS5| SocksProxy + Admin -->|reads + reloads| Config +``` + +## Configuration Model + +The proxy reads `~/.codex/config.toml`: + +- `[network_proxy]` for endpoints, mode, and toggles. +- `[network_proxy.policy]` for `allowed_domains` / `denied_domains` (and, on macOS, optional local IPC allowances). +- `[network_proxy.mitm]` for MITM CA paths and inspection settings. + +Codex is the source of truth. Approval actions update the config and trigger a proxy reload. + +## Enforcement Model + +- **Allow/deny precedence:** denylist wins; allowlist is required for access. +- **Limited mode:** only GET/HEAD/OPTIONS are permitted. HTTPS requires MITM to enforce method constraints; otherwise CONNECT is blocked with a clear reason. +- **Full mode:** all methods allowed; CONNECT tunneling is permitted without MITM. + +## macOS Sandbox Integration (Seatbelt) + +On macOS, Codex uses Seatbelt (`sandbox-exec`) for OS-level enforcement. + +Key points: + +- **Per-domain gating happens in the proxy**, not in Seatbelt: Seatbelt network rules are intentionally limited to loopback proxy ports (e.g. `localhost:3128` / `localhost:8081`) so all outbound traffic is forced through the proxy, which then applies the allow/deny policy and prompts. +- **Local IPC is deny-by-default** when proxy-restricted network access is active. Some tools rely on Unix domain sockets (e.g. the SSH agent). These are blocked unless explicitly allowed via: + - `network_proxy.policy.allow_unix_sockets` (absolute socket paths, `$SSH_AUTH_SOCK`, or the `ssh-agent` preset), and/or + - `network_proxy.policy.allow_local_binding` (if you need to bind/listen on localhost ports). + +When approvals are enabled, Codex can preflight commands that appear to require the SSH agent and prompt to allow the SSH agent socket before running. + +## Logging and Auditability + +The proxy logs: + +- Allow/deny decisions (host, client, reason). +- Policy updates (allowlist/denylist adds/removes). +- Mode changes and config reloads. +- MITM lifecycle events (CA generated, TLS established). + +## Decision to Make: Preflight Strictness + +Codex performs a preflight check before running some commands. Preflight currently scans CLI args for URLs on known network tools (curl, git, etc.) and shell `-c` snippets. + +We need to decide how strict preflight should be: + +Option A: **Heuristic preflight (current)** +- Pros: catches obvious `curl https://...` style commands early. +- Cons: misses dynamic URLs inside scripts; can still overprompt on shell snippets. + +Option B: **Strict preflight** +- Only preflight when a URL argument is present in the command. +- For everything else, rely on the proxy `/blocked` prompt at connect time. +- Pros: fewer false positives, clearer user experience. +- Cons: fewer early prompts; approvals shift to runtime events. + +Decision: **TBD**. We should choose a configuration flag (`network_proxy.preflight_mode = "heuristic" | "strict"`) and default based on observed UX. + +## Open Items + +- Finalize preflight strictness and expose a config toggle if needed. +- Confirm documentation for MITM trust steps and CA injection into sandboxed commands. diff --git a/docs/network-proxy-quickstart.md b/docs/network-proxy-quickstart.md new file mode 100644 index 0000000000..ee9533ad5b --- /dev/null +++ b/docs/network-proxy-quickstart.md @@ -0,0 +1,93 @@ +# Codex Network Proxy Quickstart (Local) + +This is a compact guide to build and validate the Codex network proxy locally. + +## Build + +From the Codex repo: + +```bash +cd /Users/viyatb/code/codex/codex-rs +cargo build -p codex-network-proxy +``` + +For MITM support: + +```bash +cargo build -p codex-network-proxy --features mitm +``` + +## Configure + +Add this to `~/.codex/config.toml`: + +```toml +[network_proxy] +enabled = true +proxy_url = "http://127.0.0.1:3128" +admin_url = "http://127.0.0.1:8080" +mode = "limited" # or "full" +poll_interval_ms = 1000 + +[network_proxy.policy] +allowed_domains = ["example.com", "*.github.com"] +denied_domains = ["metadata.google.internal", "169.254.*"] +# macOS only: allow specific local IPC when proxy-restricted. +allow_local_binding = false +# Example: allow SSH agent socket for git/ssh. +allow_unix_sockets = ["$SSH_AUTH_SOCK"] + +[network_proxy.mitm] +enabled = false +``` + +## Run the proxy + +```bash +cd /Users/viyatb/code/codex/codex-rs +cargo run -p codex-network-proxy -- proxy +``` + +With MITM: + +```bash +cargo run -p codex-network-proxy --features mitm -- proxy +``` + +## Test with curl + +HTTP/HTTPS via proxy: + +```bash +export HTTP_PROXY="http://127.0.0.1:3128" +export HTTPS_PROXY="http://127.0.0.1:3128" +curl -sS https://example.com +``` + +Limited mode + HTTPS requires MITM. If MITM is on, trust the generated CA: + +```bash +security add-trusted-cert -d -r trustRoot \ + -k ~/Library/Keychains/login.keychain-db \ + ~/.codex/network_proxy/mitm/ca.pem +``` + +Or pass the CA directly: + +```bash +curl --cacert ~/.codex/network_proxy/mitm/ca.pem -sS https://example.com +``` + +## Admin endpoints + +Reload config after edits: + +```bash +curl -fsS -X POST http://127.0.0.1:8080/reload +``` + +Switch modes: + +```bash +curl -fsS -X POST http://127.0.0.1:8080/mode -d '{"mode":"full"}' +```