From e7de7a61366315492278e8445a20522ee1039ea1 Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Mon, 5 Oct 2026 06:18:05 -0700 Subject: [PATCH 1/3] conformance: the suite's host connector (ARCHITECT Q-P4-9): the http need served by busbar's connector, deliveries reaching a real local HTTPS far end; pinned to busbar lane-p4-fleet-doors 324e30d2b0 - declares.json states the sink's network need (`needs: ["http"]`), the data the fleet render reads. - Rendered by `busbar-release plugin render busbar-export-webhook --tree . --out . --pin 324e30d2b0... 1.6.0` (busbar-release branch p4-conf-host): the pin (.busbar-ref, Cargo.toml, the workflow refs), the host adapter (export-webhook-plugin/tests/support/conformance_host.rs), its dev-dependency rows (busbar-core-connector with test-support, busbar-transport-tcp and -http at busbar's revs), the one-contract [patch] and deny.toml's sources. Cargo.lock re-resolved from busbar's lock at the pin. - tests/conformance.rs adopts the suite's `host:` (the rendered host, with the suite's far end answering HTTP 200 once a whole request is read) and `tls:` (the host's test anchors); the plugin crate takes the host's dev-dependencies; conformance.json's target is the far end (https://localhost:51655/busbar) and `deliver #0` is the dialing step that must resume. Local: fmt, clippy -D warnings, cargo deny, cargo test --workspace and the release conformance run (9/9: the 6 suite arms incl. red_a_networked_door_with_no_connection_table_is_refused, the host's TLS upgrade against the anchors, RED with them withheld, and an http need through the framer); BUSBAR_CONFORMANCE_RED=count fails with "crossing(s), pinned". --- .busbar-ref | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 +- .github/workflows/repin.yml | 2 +- Cargo.lock | 1633 +++++++++++++++-- Cargo.toml | 35 +- deny.toml | 24 +- export-webhook-plugin/Cargo.toml | 6 + export-webhook-plugin/tests/conformance.json | 3 +- export-webhook-plugin/tests/conformance.rs | 33 + .../tests/support/conformance_host.rs | 496 +++++ export-webhook/declares.json | 3 + 12 files changed, 2050 insertions(+), 193 deletions(-) create mode 100644 export-webhook-plugin/tests/support/conformance_host.rs diff --git a/.busbar-ref b/.busbar-ref index 13aa47f..a43f758 100644 --- a/.busbar-ref +++ b/.busbar-ref @@ -1 +1 @@ -8420e88cacba281d07d476161accf05dc597ab44 1.6.0 +324e30d2b0725c9dc8538580b691a487b336a954 1.6.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98df0f7..a8c428f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ permissions: jobs: ci: - uses: GetBusbar/busbar/.github/workflows/plugin-ci.yml@8420e88cacba281d07d476161accf05dc597ab44 + uses: GetBusbar/busbar/.github/workflows/plugin-ci.yml@324e30d2b0725c9dc8538580b691a487b336a954 with: service: none busbar_checkout: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d89201..328b1f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: secrets: inherit release: needs: ci - uses: GetBusbar/busbar/.github/workflows/plugin-release.yml@8420e88cacba281d07d476161accf05dc597ab44 + uses: GetBusbar/busbar/.github/workflows/plugin-release.yml@324e30d2b0725c9dc8538580b691a487b336a954 with: plugin_crate: busbar-export-webhook-plugin manifest_name: busbar-export-webhook @@ -41,7 +41,7 @@ jobs: consumer-verify: needs: release if: ${{ !cancelled() }} - uses: GetBusbar/busbar/.github/workflows/plugin-consumer-verify.yml@8420e88cacba281d07d476161accf05dc597ab44 + uses: GetBusbar/busbar/.github/workflows/plugin-consumer-verify.yml@324e30d2b0725c9dc8538580b691a487b336a954 with: version: ${{ github.ref_name }} asset_prefix: busbar-export-webhook diff --git a/.github/workflows/repin.yml b/.github/workflows/repin.yml index 6694dfd..ceb72f0 100644 --- a/.github/workflows/repin.yml +++ b/.github/workflows/repin.yml @@ -28,7 +28,7 @@ permissions: jobs: repin: - uses: GetBusbar/busbar/.github/workflows/plugin-repin.yml@8420e88cacba281d07d476161accf05dc597ab44 + uses: GetBusbar/busbar/.github/workflows/plugin-repin.yml@324e30d2b0725c9dc8538580b691a487b336a954 with: busbar_sha: ${{ github.event.client_payload.sha || inputs.busbar_sha }} busbar_version: ${{ github.event.client_payload.version || inputs.busbar_version }} diff --git a/Cargo.lock b/Cargo.lock index a850a7b..3e843c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,82 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "asn1-rs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.3", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "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.117", +] + [[package]] name = "async-trait" version = "0.1.92" @@ -19,18 +95,103 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + [[package]] name = "block-buffer" version = "0.10.4" @@ -40,13 +201,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + [[package]] name = "busbar-contract" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=8420e88cacba281d07d476161accf05dc597ab44#8420e88cacba281d07d476161accf05dc597ab44" +source = "git+https://www.github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", "futures", "hex", "http", @@ -63,6 +230,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "busbar-core-connector" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", + "busbar-kernel", + "crc32fast", + "dimpl", + "futures", + "libc", + "rcgen", + "ring", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "socket2", + "tokio", + "tokio-rustls", + "tokio-util", + "webpki-roots", + "zeroize", +] + [[package]] name = "busbar-export-webhook" version = "1.5.0" @@ -79,25 +270,129 @@ name = "busbar-export-webhook-plugin" version = "1.5.0" dependencies = [ "busbar-contract", + "busbar-core-connector", "busbar-export-webhook", "busbar-export-webhook-plugin", "busbar-plugin-loader", + "busbar-transport-http", + "busbar-transport-tcp", + "tokio", +] + +[[package]] +name = "busbar-kernel" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "arc-swap", + "async-trait", + "axum", + "base64 0.22.1", + "bumpalo", + "busbar-contract", + "busbar-kernel-audit", + "busbar-kernel-breaker", + "busbar-kernel-egress", + "busbar-kernel-identity", + "busbar-kernel-ledger", + "busbar-kernel-scope", + "busbar-kernel-wal", + "busbar-plugin-loader", + "bytes", + "crc32fast", + "ed25519-dalek", + "futures", + "getrandom 0.3.4", + "hex", + "http", + "http-body", + "http-body-util", + "httpdate", + "hyper", + "hyper-util", + "indexmap", + "metrics", + "metrics-exporter-prometheus", + "metrics-util", + "ring", + "serde", + "serde_json", + "serde_urlencoded", + "serde_yaml_ng", + "sonic-rs", + "tokio", + "tokio-util", + "tower", + "tracing", + "tracing-subscriber", + "url", + "zeroize", +] + +[[package]] +name = "busbar-kernel-audit" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", + "ed25519-dalek", + "ring", + "zeroize", +] + +[[package]] +name = "busbar-kernel-breaker" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", + "httpdate", +] + +[[package]] +name = "busbar-kernel-egress" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", + "bytes", + "futures", +] + +[[package]] +name = "busbar-kernel-identity" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", + "hex", + "ring", + "serde", + "tracing", ] [[package]] name = "busbar-kernel-ledger" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=8420e88cacba281d07d476161accf05dc597ab44#8420e88cacba281d07d476161accf05dc597ab44" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" dependencies = [ "busbar-contract", "ring", "serde", ] +[[package]] +name = "busbar-kernel-scope" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +dependencies = [ + "busbar-contract", +] + [[package]] name = "busbar-kernel-wal" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=8420e88cacba281d07d476161accf05dc597ab44#8420e88cacba281d07d476161accf05dc597ab44" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" dependencies = [ "busbar-contract", "ring", @@ -106,7 +401,7 @@ dependencies = [ [[package]] name = "busbar-plugin-loader" version = "1.5.0" -source = "git+https://github.com/GetBusbar/busbar?rev=8420e88cacba281d07d476161accf05dc597ab44#8420e88cacba281d07d476161accf05dc597ab44" +source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" dependencies = [ "busbar-contract", "busbar-kernel-ledger", @@ -125,6 +420,32 @@ dependencies = [ "tracing", ] +[[package]] +name = "busbar-transport-http" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar-transport-http?rev=fc91230af97997994e9206124ee7414f3aec6eee#fc91230af97997994e9206124ee7414f3aec6eee" +dependencies = [ + "busbar-contract", + "bytes", + "futures", + "http", + "http-body-util", + "hyper", + "hyper-util", + "memchr", + "serde_json", + "tokio", + "tokio-util", +] + +[[package]] +name = "busbar-transport-tcp" +version = "1.6.0" +source = "git+https://github.com/GetBusbar/busbar-transport-tcp?rev=89d08ebcb91e5b2d4001b667fba151d9bc09d22d#89d08ebcb91e5b2d4001b667fba151d9bc09d22d" +dependencies = [ + "busbar-contract", +] + [[package]] name = "bytes" version = "1.12.1" @@ -171,6 +492,21 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crypto-common" version = "0.1.7" @@ -208,6 +544,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + [[package]] name = "der" version = "0.7.10" @@ -218,6 +560,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.3", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + [[package]] name = "digest" version = "0.10.7" @@ -228,6 +590,21 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dimpl" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07d467d37bfdcc290bb8dcbedc8ca356eb730e46459b1687f98c3bae28aa6814" +dependencies = [ + "arrayvec", + "log", + "nom 8.0.0", + "once_cell", + "rand", + "subtle", + "time", +] + [[package]] name = "displaydoc" version = "0.2.6" @@ -269,6 +646,39 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "evmap" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8874945f036109c72242964c1174cf99434e30cfa45bf45fedc983f50046f8" +dependencies = [ + "hashbag", + "left-right", + "smallvec", +] + +[[package]] +name = "faststr" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca7d44d22004409a61c393afb3369c8f7bb74abcae49fe249ee01dcc3002113" +dependencies = [ + "bytes", + "rkyv", + "serde", + "simdutf8", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -301,6 +711,18 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -399,17 +821,32 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "generator" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows-link", + "windows-result", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" @@ -431,6 +868,40 @@ dependencies = [ "wasip2", ] +[[package]] +name = "h2" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "839c0e8a181239723652be9062bb56ca5bf5f64011f73b623f6f4fc59086a228" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbag" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7040a10f52cba493ddb09926e15d10a9d8a28043708a405931fe4c6f19fac064" + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -454,85 +925,80 @@ dependencies = [ ] [[package]] -name = "icu_collections" -version = "2.2.0" +name = "http-body" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", + "bytes", + "http", ] [[package]] -name = "icu_locale_core" -version = "2.2.0" +name = "http-body-util" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", ] [[package]] -name = "icu_normalizer" -version = "2.2.0" +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] -name = "icu_normalizer_data" -version = "2.2.0" +name = "httpdate" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] -name = "icu_properties" -version = "2.2.0" +name = "hyper" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", ] [[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" +name = "hyper-util" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] @@ -548,12 +1014,22 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.2" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279259b0ac81c89d11c290495fdcfa96ea3643b7df311c138b6fe8ca5237f0f8" +dependencies = [ + "idna_mapping", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna_mapping" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +checksum = "11c13906586a4b339310541a274dd927aff6fcbb5b8e3af90634c4b31681c792" dependencies = [ - "icu_normalizer", - "icu_properties", + "unicode-joining-type", ] [[package]] @@ -563,7 +1039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -574,6 +1050,35 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "js-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "left-right" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0c21e4c8ff95f487fb34e6f9182875f42c84cef966d29216bf115d9bba835a" +dependencies = [ + "crossbeam-utils", + "loom", + "slab", +] + [[package]] name = "libc" version = "0.2.189" @@ -590,24 +1095,100 @@ dependencies = [ "windows-link", ] -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - [[package]] name = "log" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "memchr" version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +[[package]] +name = "metrics" +version = "0.24.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89550ee9f79e88fef3119de263694973a8adb26c21d75322164fb8c493039fe2" +dependencies = [ + "portable-atomic", + "rapidhash", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db0d8f1fc9e62caebd0319e11eaec5822b0186c171568f0480b46a0137f9108" +dependencies = [ + "base64 0.22.1", + "evmap", + "indexmap", + "metrics", + "metrics-util", + "quanta", + "thiserror", +] + +[[package]] +name = "metrics-util" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96f8722f8562635f92f8ed992f26df0532266eb03d5202607c20c0d7e9745e13" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.16.1", + "metrics", + "quanta", + "rand", + "rand_xoshiro", + "rapidhash", + "sketches-ddsketch", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.9.1" @@ -618,12 +1199,124 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "munge" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e17401f259eba956ca16491461b6e8f72913a0a114e39736ce404410f915a0c" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "pem" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d354a98a3d1251555de99e8fdd8afda05573c31b82f59063a7b0a29b5527f120" +dependencies = [ + "base64 0.23.1", + "serde_core", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -647,12 +1340,24 @@ dependencies = [ ] [[package]] -name = "potential_utf" -version = "0.1.5" +name = "portable-atomic" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerovec", + "zerocopy", ] [[package]] @@ -664,6 +1369,41 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quote" version = "1.0.45" @@ -679,6 +1419,35 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rancor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" +dependencies = [ + "ptr_meta", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -688,6 +1457,99 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rcgen" +version = "0.14.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8774e05a7d0de114588e6a28fe7e71694b82614ed569d86d8b389dfbc98b8ad8" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rend" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" + [[package]] name = "ring" version = "0.17.14" @@ -699,7 +1561,36 @@ dependencies = [ "getrandom 0.2.17", "libc", "untrusted", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rkyv" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9776093b7ca170454ab1406954f7b7d97a57c51dc6c0642957fb2ef25c2d399" +dependencies = [ + "bytes", + "hashbrown 0.17.1", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c25ef604ac7dd839d44d64648952ea23c97866f124ff671b0ed2cf3ad9bb06e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", ] [[package]] @@ -711,12 +1602,67 @@ 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 = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "ryu" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "semver" version = "1.0.28" @@ -766,6 +1712,29 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_yaml_ng" version = "0.10.0" @@ -790,19 +1759,38 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -811,6 +1799,18 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "sketches-ddsketch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" + [[package]] name = "slab" version = "0.4.12" @@ -823,6 +1823,55 @@ version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "sonic-number" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c350a05f295f922fc153a3af8b443c10db70904a9291a624ddb6058c6110d0" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "sonic-rs" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756586caeeb21126a57c17d1ef2b9386e2613ba784aae0f27104f5e9982335ec" +dependencies = [ + "ahash", + "bumpalo", + "bytes", + "cfg-if", + "faststr", + "itoa", + "ref-cast", + "serde", + "simdutf8", + "sonic-number", + "sonic-simd", + "thiserror", + "zmij", +] + +[[package]] +name = "sonic-simd" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f99e664ecd2d85a68c87e3c7a3cfe691f647ea9e835de984aba4d54a41f817d4" +dependencies = [ + "cfg-if", +] + [[package]] name = "spki" version = "0.7.3" @@ -833,12 +1882,6 @@ dependencies = [ "der", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "subtle" version = "2.6.1" @@ -867,6 +1910,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + [[package]] name = "synstructure" version = "0.13.2" @@ -889,30 +1938,165 @@ dependencies = [ ] [[package]] -name = "tinystr" -version = "0.8.3" +name = "thiserror" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "displaydoc", - "zerovec", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", ] +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -950,18 +2134,63 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-joining-type" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d00a78170970967fdb83f9d49b92f959ab2bb829186b113e4f4604ad98e180" + +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -992,6 +2221,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -1004,6 +2243,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1019,12 +2267,107 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1034,6 +2377,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1105,53 +2457,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "yoke" -version = "0.8.2" +name = "x509-parser" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror", + "time", ] [[package]] -name = "yoke-derive" -version = "0.8.2" +name = "yasna" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", + "bit-vec", + "time", ] [[package]] -name = "zerofrom" -version = "0.1.8" +name = "zerocopy" +version = "0.8.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +checksum = "bce33a6288fa3f072a8c2c7d0f2fdbb90e28298f0135c1f99b96c3db2efcc60b" dependencies = [ - "zerofrom-derive", + "zerocopy-derive", ] [[package]] -name = "zerofrom-derive" -version = "0.1.7" +name = "zerocopy-derive" +version = "0.8.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "8fd425244944f4ab65ccff928e7323354c5a018c75838362fdce749dfad2ee1e" dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "synstructure", ] [[package]] @@ -1160,39 +2510,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index 6f7e3cb..931d029 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ # `.busbar-ref`; no sibling-checkout path dependency ships in any manifest. # # THIRD-PARTY VERSIONS ARE THE FLEET'S, NOT THIS REPO'S. The table below is busbar's own root -# `[workspace.dependencies]` (third-party rows) at busbar 8fc3b1b2a6d123575a77ce505e501b595fb24cef, followed by the plugin-only rows -# of busbar's `.github/fleet/deps.toml` at 8fc3b1b2a6d123575a77ce505e501b595fb24cef. A member takes a crate with +# `[workspace.dependencies]` (third-party rows) at busbar 324e30d2b0725c9dc8538580b691a487b336a954, followed by the plugin-only rows +# of busbar's `.github/fleet/deps.toml` at 324e30d2b0725c9dc8538580b691a487b336a954. A member takes a crate with # `{ workspace = true }` (adding features if it needs them); a crate in neither table is a new # `deps.toml` row in busbar first. CI holds this repo's Cargo.lock to busbar's lock at the pin. [workspace] @@ -29,9 +29,15 @@ publish = false repository = "https://github.com/GetBusbar/busbar-export-webhook" [workspace.dependencies] -busbar-contract = { git = "https://github.com/GetBusbar/busbar", rev = "8420e88cacba281d07d476161accf05dc597ab44" } -busbar-plugin-loader = { git = "https://github.com/GetBusbar/busbar", rev = "8420e88cacba281d07d476161accf05dc597ab44" } -# busbar's root [workspace.dependencies], third-party rows, at 8fc3b1b2a6d123575a77ce505e501b595fb24cef +busbar-contract = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } +busbar-plugin-loader = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } +# THE SUITE'S HOST CONNECTOR (dev-only; export-webhook-plugin/tests/support/conformance_host.rs, +# rendered because the declares file states network needs): busbar's connector and its TLS +# test kit at the pin, and the transport framers those needs name, at the revs busbar links. +busbar-core-connector = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954", features = ["test-support"] } +busbar-transport-http = { git = "https://github.com/GetBusbar/busbar-transport-http", rev = "fc91230af97997994e9206124ee7414f3aec6eee" } +busbar-transport-tcp = { git = "https://github.com/GetBusbar/busbar-transport-tcp", rev = "89d08ebcb91e5b2d4001b667fba151d9bc09d22d" } +# busbar's root [workspace.dependencies], third-party rows, at 324e30d2b0725c9dc8538580b691a487b336a954 a2a-lf = "0.3.0" a2a-pb = "0.2.0" arc-swap = "1" @@ -50,14 +56,13 @@ futures = "0.3" getrandom = "0.3" h2 = "0.4" hex = "0.4.3" -hmac = "0.13.0" http = "1" http-body = "1" http-body-util = "0.1" httpdate = "1.0" hyper = { version = "1", default-features = false, features = ["server", "client", "http1", "http2"] } -hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1", default-features = false, features = ["client-legacy", "http1", "http2", "server-auto", "server-graceful", "service", "tokio"] } +idna_adapter = "=1.1.0" indexmap = { version = "2", features = ["serde"] } jsonschema = { version = "0.49", default-features = false } libc = "0.2" @@ -68,7 +73,7 @@ memchr = "2" metrics = "0.24.6" metrics-exporter-prometheus = { version = "0.18.3", default-features = false } metrics-util = { version = "0.20.4", default-features = false } -oauth-as = { version = "1.0.0", features = ["http", "jwt", "consent", "resource-metadata"] } +oauth-as = { version = "1.0.0", features = ["http", "jwt", "consent", "resource-metadata", "par", "dpop", "client-assertion"] } opentelemetry-proto = { version = "0.32", default-features = false, features = ["gen-tonic-messages", "trace"] } proc-macro2 = { version = "1", features = ["span-locations"] } proptest = "1" @@ -84,7 +89,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" serde_urlencoded = "0.7" serde_yaml = { package = "serde_yaml_ng", version = "0.10" } -sha2 = "0.11.0" +sha2 = "0.10" smallvec = "1" socket2 = { version = "0.6", features = ["all"] } sonic-rs = "0.5" @@ -108,11 +113,19 @@ url = "2" webpki = { package = "rustls-webpki", version = "0.103", default-features = false, features = ["std", "ring"] } webpki-roots = "1" zeroize = "1" -# busbar .github/fleet/deps.toml [plugin-deps], at 8fc3b1b2a6d123575a77ce505e501b595fb24cef +# busbar .github/fleet/deps.toml [plugin-deps], at 324e30d2b0725c9dc8538580b691a487b336a954 ldap3 = { version = "0.12", default-features = false, features = ["sync"] } -mysql = { version = "26", default-features = false, features = ["minimal"] } +mysql = { version = "28", default-features = false, features = ["minimal-rust"] } +mysql_common = { version = "0.35", default-features = false } +percent-encoding = "2" postgres = "0.19" redis = { version = "1", default-features = false, features = ["script"] } rusqlite = { version = "0.40", features = ["bundled"] } ulid = "1" +# ONE busbar-contract (the suite's host connector): the transport framers above name +# busbar-contract at their own revs of busbar; this repo's pin serves them all, as busbar +# patches them to its own tree. The source is busbar spelled through www.github.com: Cargo +# refuses a patch that names the source it patches. +[patch."https://github.com/GetBusbar/busbar"] +busbar-contract = { git = "https://www.github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } diff --git a/deny.toml b/deny.toml index a76e4f0..c6a1b83 100644 --- a/deny.toml +++ b/deny.toml @@ -1,5 +1,5 @@ # RENDERED by `busbar-release plugin sync` from GetBusbar/busbar-release template/ and busbar's -# `.github/fleet/deps.toml` at 8fc3b1b2a6d123575a77ce505e501b595fb24cef; a hand edit is overwritten by the next sync. CI runs +# `.github/fleet/deps.toml` at 324e30d2b0725c9dc8538580b691a487b336a954; a hand edit is overwritten by the next sync. CI runs # `cargo deny check` on it (busbar's plugin-ci.yml at the pin). The license allowlist is busbar's own; # the one reviewed git source is busbar itself, at the pin. [graph] @@ -88,8 +88,6 @@ deny = [ { crate = "h2:>=0.5.0", reason = "busbar resolves h2 to 0.4.18; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hex:<0.4.0", reason = "busbar resolves hex to 0.4.3; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hex:>=0.5.0", reason = "busbar resolves hex to 0.4.3; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "hmac:<0.13.0", reason = "busbar resolves hmac to 0.13.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "hmac:>=0.14.0", reason = "busbar resolves hmac to 0.13.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "http:<1.0.0", reason = "busbar resolves http to 1.4.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "http:>=2.0.0", reason = "busbar resolves http to 1.4.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "http-body:<1.0.0", reason = "busbar resolves http-body to 1.1.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, @@ -100,10 +98,10 @@ deny = [ { crate = "httpdate:>=2.0.0", reason = "busbar resolves httpdate to 1.0.3; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hyper:<1.0.0", reason = "busbar resolves hyper to 1.11.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hyper:>=2.0.0", reason = "busbar resolves hyper to 1.11.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "hyper-rustls:<0.27.0", reason = "busbar resolves hyper-rustls to 0.27.9; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "hyper-rustls:>=0.28.0", reason = "busbar resolves hyper-rustls to 0.27.9; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hyper-util:<0.1.0", reason = "busbar resolves hyper-util to 0.1.20; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "hyper-util:>=0.2.0", reason = "busbar resolves hyper-util to 0.1.20; a plugin may not pull a second version (OWNER 2026-10-02)" }, + { crate = "idna_adapter:<1.0.0", reason = "busbar resolves idna_adapter to 1.1.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, + { crate = "idna_adapter:>=2.0.0", reason = "busbar resolves idna_adapter to 1.1.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "indexmap:<2.0.0", reason = "busbar resolves indexmap to 2.14.2; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "indexmap:>=3.0.0", reason = "busbar resolves indexmap to 2.14.2; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "jsonschema:<0.49.0", reason = "busbar resolves jsonschema to 0.49.9; a plugin may not pull a second version (OWNER 2026-10-02)" }, @@ -156,8 +154,8 @@ deny = [ { crate = "serde_urlencoded:>=0.8.0", reason = "busbar resolves serde_urlencoded to 0.7.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "serde_yaml_ng:<0.10.0", reason = "busbar resolves serde_yaml_ng to 0.10.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "serde_yaml_ng:>=0.11.0", reason = "busbar resolves serde_yaml_ng to 0.10.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "sha2:<0.10.0", reason = "busbar resolves sha2 to 0.10.9, 0.11.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, - { crate = "sha2:>=0.12.0", reason = "busbar resolves sha2 to 0.10.9, 0.11.0; a plugin may not pull a second version (OWNER 2026-10-02)" }, + { crate = "sha2:<0.10.0", reason = "busbar resolves sha2 to 0.10.9; a plugin may not pull a second version (OWNER 2026-10-02)" }, + { crate = "sha2:>=0.11.0", reason = "busbar resolves sha2 to 0.10.9; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "smallvec:<1.0.0", reason = "busbar resolves smallvec to 1.16.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "smallvec:>=2.0.0", reason = "busbar resolves smallvec to 1.16.1; a plugin may not pull a second version (OWNER 2026-10-02)" }, { crate = "socket2:<0.6.0", reason = "busbar resolves socket2 to 0.6.4; a plugin may not pull a second version (OWNER 2026-10-02)" }, @@ -212,16 +210,8 @@ skip = [ { crate = "base64@0.23.1", reason = "busbar's own lock holds this duplicate" }, { crate = "bit-vec@0.8.0", reason = "busbar's own lock holds this duplicate" }, { crate = "bit-vec@0.9.1", reason = "busbar's own lock holds this duplicate" }, - { crate = "block-buffer@0.10.4", reason = "busbar's own lock holds this duplicate" }, - { crate = "block-buffer@0.12.0", reason = "busbar's own lock holds this duplicate" }, - { crate = "const-oid@0.10.2", reason = "busbar's own lock holds this duplicate" }, - { crate = "const-oid@0.9.6", reason = "busbar's own lock holds this duplicate" }, { crate = "cpufeatures@0.2.17", reason = "busbar's own lock holds this duplicate" }, { crate = "cpufeatures@0.3.0", reason = "busbar's own lock holds this duplicate" }, - { crate = "crypto-common@0.1.7", reason = "busbar's own lock holds this duplicate" }, - { crate = "crypto-common@0.2.2", reason = "busbar's own lock holds this duplicate" }, - { crate = "digest@0.10.7", reason = "busbar's own lock holds this duplicate" }, - { crate = "digest@0.11.3", reason = "busbar's own lock holds this duplicate" }, { crate = "foldhash@0.1.5", reason = "busbar's own lock holds this duplicate" }, { crate = "foldhash@0.2.0", reason = "busbar's own lock holds this duplicate" }, { crate = "getrandom@0.2.17", reason = "busbar's own lock holds this duplicate" }, @@ -241,8 +231,6 @@ skip = [ { crate = "rand_core@0.10.1", reason = "busbar's own lock holds this duplicate" }, { crate = "rand_core@0.6.4", reason = "busbar's own lock holds this duplicate" }, { crate = "rand_core@0.9.5", reason = "busbar's own lock holds this duplicate" }, - { crate = "sha2@0.10.9", reason = "busbar's own lock holds this duplicate" }, - { crate = "sha2@0.11.0", reason = "busbar's own lock holds this duplicate" }, { crate = "syn@2.0.117", reason = "busbar's own lock holds this duplicate" }, { crate = "syn@3.0.3", reason = "busbar's own lock holds this duplicate" }, { crate = "windows-sys@0.52.0", reason = "busbar's own lock holds this duplicate" }, @@ -253,4 +241,4 @@ skip = [ unknown-registry = "deny" unknown-git = "deny" allow-registry = ["https://github.com/rust-lang/crates.io-index"] -allow-git = ["https://github.com/GetBusbar/busbar"] +allow-git = ["https://github.com/GetBusbar/busbar", "https://www.github.com/GetBusbar/busbar", "https://github.com/GetBusbar/busbar-transport-http", "https://github.com/GetBusbar/busbar-transport-tcp"] diff --git a/export-webhook-plugin/Cargo.toml b/export-webhook-plugin/Cargo.toml index 758440f..73ee610 100644 --- a/export-webhook-plugin/Cargo.toml +++ b/export-webhook-plugin/Cargo.toml @@ -35,3 +35,9 @@ busbar-export-webhook-plugin = { path = ".", features = ["dropped-in"] } # The conformance test loads the built cdylib and the linked door over the REAL loader — dev-only, # never in the shipped artifact. Same pinned rev, so one busbar source resolves. busbar-plugin-loader = { workspace = true, features = ["conformance"] } +# THE SUITE'S HOST CONNECTOR (tests/support/conformance_host.rs, rendered): busbar's connector, its +# TLS test kit, and the transport framers this plugin's needs name. Dev-only. +busbar-core-connector = { workspace = true } +busbar-transport-tcp = { workspace = true } +busbar-transport-http = { workspace = true } +tokio = { workspace = true, features = ["rt"] } diff --git a/export-webhook-plugin/tests/conformance.json b/export-webhook-plugin/tests/conformance.json index a256ecb..77d3736 100644 --- a/export-webhook-plugin/tests/conformance.json +++ b/export-webhook-plugin/tests/conformance.json @@ -1,5 +1,6 @@ { - "settings": { "url": "https://hooks.example.com/busbar" }, + "settings": { "url": "https://localhost:51655/busbar" }, + "dialing_steps": ["deliver #0"], "export": { "bad_settings": [ { "settings": {}, "refusal": "settings: missing field `url`" }, diff --git a/export-webhook-plugin/tests/conformance.rs b/export-webhook-plugin/tests/conformance.rs index 44c63fd..e595373 100644 --- a/export-webhook-plugin/tests/conformance.rs +++ b/export-webhook-plugin/tests/conformance.rs @@ -10,8 +10,41 @@ //! answering 404); every step's crossings exactly at the script's pin, the two folds equal, and the //! suite's RED arms kept. `plugin-ci.yml` runs it under `--release`. +//! +//! THE HOST (ARCHITECT Q-P4-9): the sink's `http` need is served by busbar's own connector, composed +//! as the root composes it ([`conformance_host`], rendered by the fleet template), and every delivery +//! reaches a REAL local HTTPS endpoint (the suite's far end, its certificate chained to the suite's +//! test anchors, which only the host trusts): the target in `conformance.json`'s settings. + +#[path = "support/conformance_host.rs"] +mod conformance_host; + +/// The far end's answer: an HTTP/1.1 `200` once a whole request (its head, then the +/// `content-length` body it states) has been read. +fn accepted(seen: &[u8]) -> Option> { + let end = seen.windows(4).position(|w| w == b"\r\n\r\n")? + 4; + let head = String::from_utf8_lossy(&seen[..end]).to_ascii_lowercase(); + let body = head + .lines() + .find_map(|l| l.strip_prefix("content-length:")) + .and_then(|n| n.trim().parse::().ok()) + .unwrap_or(0); + (seen.len() >= end + body).then(|| b"HTTP/1.1 200 OK\r\ncontent-length: 0\r\n\r\n".to_vec()) +} + +/// The host the suite binds the sink over, with the far end its settings name already listening. +fn host( + wake: std::sync::Arc, + anchors: Option<&str>, +) -> std::sync::Arc { + conformance_host::far_end(accepted); + conformance_host::host(wake, anchors) +} + busbar_plugin_loader::conformance_suite! { door: busbar_export_webhook::door, cdylib: "busbar_export_webhook_plugin", inputs: include_str!("conformance.json"), + host: host, + tls: conformance_host::anchors(), } diff --git a/export-webhook-plugin/tests/support/conformance_host.rs b/export-webhook-plugin/tests/support/conformance_host.rs new file mode 100644 index 0000000..28ceebf --- /dev/null +++ b/export-webhook-plugin/tests/support/conformance_host.rs @@ -0,0 +1,496 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2026 Busbar Inc and contributors +// +// RENDERED by `busbar-release plugin sync busbar-export-webhook` from GetBusbar/busbar-release +// template/conformance-host/, because this repo's declares file states network needs (`needs`: +// `http`); a hand edit is overwritten by the next sync. + +//! **THE SUITE'S HOST CONNECTOR, IN THIS PLUGIN'S OWN TEST** (ARCHITECT Q-P4-9 (d)). busbar keeps +//! only the neutral seam (`busbar_plugin_loader::conformance::Host`, the suite's `host:` and `tls:` +//! arguments); this adapter implements it the way busbar's composition root composes the process's +//! one connector — carrier -> [TLS] -> framer (`BUSBAR-1.6.0.md` THE DESIGN §5): +//! +//! * busbar's own `Connector` (`busbar-core-connector`, a dev-dependency at the pin), its framer +//! entries the transport doors this plugin's needs name (`tcp`, `http`), each loaded +//! through the loader's one load and opened as the root opens a transport door; +//! * the connector's own TLS (connsec), trusting the platform roots plus the suite's TEST trust +//! anchors (`tls:`), never handed to the plugin: no plugin holds a key, a certificate or a TLS +//! type (TRANSPORT-STACK (1)); +//! * a dial judge that admits loopback only: the suite dials the REAL local endpoints its settings +//! name, never the network; +//! * a parked read wakes the plugin's ticket through the leg dispatcher's conn waker. +//! +//! [`far_end`] is a TLS far end at [`FAR_END`] whose certificate chains to [`anchors`] (busbar's +//! test kit, `busbar_core_connector::test_support`): the plugin's `conformance.json` settings name +//! it, and its `answer` speaks the plugin's protocol. Its own tests, below, run with the suite: +//! a TLS upgrade verifies against the anchors, and is REFUSED with the anchors withheld (RED). +//! +//! The plugin's `tests/conformance.rs` mounts this file and names it: +//! +//! ```ignore +//! #[path = "support/conformance_host.rs"] +//! mod conformance_host; +//! +//! busbar_plugin_loader::conformance_suite! { +//! door: …, cdylib: …, inputs: include_str!("conformance.json"), +//! host: conformance_host::host, +//! tls: conformance_host::anchors(), +//! } +//! ``` +//! +//! with the dev-dependencies the rendered root `Cargo.toml` states (`{ workspace = true }`): +//! `busbar-core-connector`, `busbar-transport-tcp`, `busbar-transport-http`, `tokio`. + +#![allow(dead_code)] + +use std::io::{Read, Write}; +use std::net::{SocketAddr, TcpListener, ToSocketAddrs}; +use std::sync::{Arc, OnceLock}; +use std::time::{Duration, Instant}; + +use busbar_contract::abi::host::conn::connector::{ + DIRECTION_OUTBOUND, EGRESS_OPERATOR_INFRASTRUCTURE, +}; +use busbar_contract::abi::mechanism::call::{Blob, Outcome, BLOB_ABSENT}; +use busbar_contract::abi::mechanism::door::DoorFn; +use busbar_contract::abi::mechanism::lifecycle::{slot as life, OpenIn, OpenOut}; +use busbar_contract::abi::mechanism::rendering::{ReadBlob, ReadNeed}; +use busbar_contract::abi::sdk::door::{blank_in, blank_out}; +use busbar_contract::abi::transport::slot; +use busbar_contract::conn::{ + ConnError, ConnId, DeclaredConns, InstanceId, NeedId, OpenDesc, PieceKind, NO_TICKET, +}; +use busbar_contract::transport::EgressTrust; +use busbar_core_connector::framer::{Call, Crossed, DoorFacts, FramerDoor}; +use busbar_core_connector::registry::{Entry, Transports}; +use busbar_core_connector::test_support::{private_ca, ServerTls, StdServerSession, TestCa}; +use busbar_core_connector::{Connector, Judged, Verdict}; +use busbar_plugin_loader::dispatch::kinds::transport::{Transport, TransportFacts}; +use busbar_plugin_loader::dispatch::{ + load_linked, Bind, ConnTable, DispatchConfig, Dispatcher, Frame, InFrame, LinkedRow, NoSink, + OutFrame, Plugin, +}; + +/// Where [`far_end`] listens: loopback, a port of this repo's own. +pub const FAR_END: &str = "localhost:51655"; + +/// The framer doors the host serves, as the root links them: (claim, door). One row a line, +/// whatever the claims' lengths (a `vec!` would be reflowed by rustfmt). +#[allow(clippy::vec_init_then_push)] +fn doors() -> Vec<(&'static str, DoorFn)> { + use busbar_transport_http::linked::door as http_door; + use busbar_transport_tcp::linked::door as tcp_door; + // Each row is compiled against this repo's own pin of busbar-contract (the rendered `[patch]`), + // as busbar compiles the rows it links. + let mut doors: Vec<(&'static str, DoorFn)> = Vec::new(); + doors.push(("tcp", tcp_door)); + doors.push(("http", http_door)); + doors +} + +/// The suite's test CA: [`anchors`] is its certificate, [`far_end`] serves a leaf it signed. +fn ca() -> &'static TestCa { + static CA: OnceLock = OnceLock::new(); + CA.get_or_init(private_ca) +} + +/// THE SUITE'S TEST TRUST ANCHORS (PEM), for `conformance_suite!`'s `tls:`. +#[must_use] +pub fn anchors() -> &'static str { + &ca().ca_pem +} + +/// THE HOST CONNECTOR (`busbar_plugin_loader::conformance::Host`): one per leg. +/// +/// # Panics +/// The anchors do not parse, a transport door does not load or open, or the view does not compose. +#[must_use] +pub fn host(wake: Arc, anchors: Option<&str>) -> Arc { + // The reactor a socket a plugin opens from a dispatcher worker registers on, as the root + // installs it (`root::connector::io_reactor`): the connector's own I/O thread. + busbar_core_connector::io::install_process_reactor(io_reactor()); + let trust = EgressTrust { + extra_anchors: anchors.map(pem_certs).unwrap_or_default(), + ..EgressTrust::default() + }; + let tls = busbar_core_connector::tls::client::build_client_config(&trust) + .unwrap_or_else(|e| panic!("the host's connection security does not build: {e}")); + let view = Transports::new(entries()) + .unwrap_or_else(|e| panic!("the host's transport doors do not compose: {e}")); + Arc::new(Connector::serving( + view, + Arc::new(loopback), + Some(Arc::new(tls)), + wake, + )) +} + +/// The connector's I/O thread: a single-threaded runtime of its own whose reactor drives every +/// socket the plugin opens from a dispatcher worker. Built once. +fn io_reactor() -> tokio::runtime::Handle { + static IO: OnceLock = OnceLock::new(); + IO.get_or_init(|| { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("the host's I/O runtime builds"); + let handle = rt.handle().clone(); + std::thread::Builder::new() + .name("conformance-host-io".into()) + .spawn(move || rt.block_on(std::future::pending::<()>())) + .expect("the host's I/O thread starts"); + handle + }) + .clone() +} + +/// THE DIAL JUDGE: a loopback address (a literal, or a name that resolves to one) and nothing else. +fn loopback(dest: &str, _class: u32, _done: Judged) -> Option> { + let refused = busbar_contract::abi::host::service::DEST_UNRESOLVABLE; + let at = dest + .to_socket_addrs() + .ok() + .and_then(|mut a| a.find(|a| a.ip().is_loopback())); + Some(at.ok_or(refused)) +} + +/// Every certificate in `pem`, DER. +fn pem_certs(pem: &str) -> Vec> { + let certs = busbar_core_connector::test_support::certs_from_pem(pem); + assert!( + !certs.is_empty(), + "the suite's trust anchors hold no certificate" + ); + certs +} + +/// The dispatcher the host's transport doors are adopted by. +fn transport_dispatcher() -> &'static Dispatcher { + static ONE: OnceLock = OnceLock::new(); + ONE.get_or_init(|| Dispatcher::new(DispatchConfig::default())) +} + +/// The framer entries: each door loaded through the one loader and opened with no settings, as +/// the root opens a transport door that declares none it reads. +fn entries() -> Vec { + doors() + .into_iter() + .map(|(claim, door)| { + let bind = Bind { + instance: Arc::from(claim), + max_inflight_cap: 1024, + sink: Arc::new(NoSink), + dispatcher: transport_dispatcher().adopter(), + // A transport door is a framer the connector drives: it declares no need. + conns: ConnTable::NoNeeds, + }; + let plugin = LinkedRow::of(door) + .and_then(|row| load_linked::(&row, bind)) + .unwrap_or_else(|e| panic!("the host's transport `{claim}` does not load: {e}")); + Entry { + door: Arc::new(Opened::open(plugin, claim)), + alpn: Vec::new(), + } + }) + .collect() +} + +/// One transport door, opened, as the connector reaches it (the root's `doors::Dispatched`). +struct Opened { + plugin: Plugin, + facts: DoorFacts, +} + +impl Opened { + fn open(plugin: Plugin, claim: &str) -> Self { + let stated = plugin + .context::() + .cloned() + .unwrap_or_else(|| panic!("the host's transport `{claim}` states no transport tail")); + let mut i: OpenIn = blank_in(); + i.settings = Blob { + ptr: std::ptr::null(), + len: 0, + fmt: BLOB_ABSENT, + flags: 0, + }; + let mut f = Frame::new(i, blank_out::()); + let opened = plugin.call(life::OPEN, &mut f); + assert_eq!( + opened.outcome, + Outcome::Ready, + "the host's transport `{claim}` does not open" + ); + plugin + .ready(transport_dispatcher(), Duration::from_secs(10)) + .unwrap_or_else(|e| panic!("the host's transport `{claim}` is not ready: {e}")); + let facts = DoorFacts { + name: plugin.name().to_owned(), + claims: stated.claims, + composes_over: stated.composes_over, + }; + Self { plugin, facts } + } +} + +/// One crossing through the dispatcher: the host's `in`/`out` copied in, the answer copied back. +fn go(p: &Plugin, s: u32, i: &mut I, o: &mut O) -> Crossed { + let mut f = Frame::new(*i, *o); + let c = p.call(s, &mut f); + *i = f.input; + *o = f.out; + Crossed { + outcome: c.outcome, + error: c.error, + } +} + +impl FramerDoor for Opened { + fn facts(&self) -> &DoorFacts { + &self.facts + } + + fn cross(&self, call: Call<'_>) -> Crossed { + let p = &self.plugin; + match call { + Call::Locate(i, o) => go(p, slot::LOCATE, i, o), + Call::Begin(i, o) => go(p, slot::BEGIN, i, o), + Call::Ingest(i, o) => go(p, slot::INGEST, i, o), + Call::Emit(i, o) => go(p, slot::EMIT, i, o), + Call::Encode(i, o) => go(p, slot::ENCODE, i, o), + Call::Refuse(i, o) => go(p, slot::REFUSE, i, o), + Call::Finish(i, o) => go(p, slot::FINISH, i, o), + Call::Detach(i, o) => go(p, slot::DETACH, i, o), + Call::Adopt(i, o) => go(p, slot::ADOPT, i, o), + Call::Timer(i, o) => go(p, slot::TIMER, i, o), + } + } +} + +// ---- the far end ---- + +/// What a far end answers a connection: given every byte it has read so far, the bytes to send +/// back and close (`Some`), or `None` to read on. +pub type Answer = fn(&[u8]) -> Option>; + +/// THE SUITE'S TLS FAR END at [`FAR_END`] (started once; later calls are no-ops): every connection's +/// handshake is busbar's test kit's, with a `localhost` certificate [`anchors`] trusts, and its +/// bytes are answered by `answer`. +/// +/// # Panics +/// [`FAR_END`] cannot be bound. +pub fn far_end(answer: Answer) { + static STARTED: OnceLock<()> = OnceLock::new(); + STARTED.get_or_init(|| { + let listener = TcpListener::bind(FAR_END) + .unwrap_or_else(|e| panic!("the suite's far end cannot bind {FAR_END}: {e}")); + serve(listener, answer); + }); +} + +/// Serve `listener` over TLS with a leaf the test CA signed, answering each connection by `answer`. +fn serve(listener: TcpListener, answer: Answer) { + let tls = ServerTls::new(&[ca().leaf_der.clone()], &ca().key_der, None, &[]) + .unwrap_or_else(|e| panic!("the suite's far end has no TLS identity: {e}")); + std::thread::spawn(move || { + for tcp in listener.incoming() { + let Ok(tcp) = tcp else { return }; + let tls = tls.clone(); + std::thread::spawn(move || { + if let Ok(mut s) = tls.accept_std(tcp) { + if s.handshake_ok() { + reply(&mut s, answer); + } + } + }); + } + }); +} + +fn reply(s: &mut StdServerSession, answer: Answer) { + let mut seen = Vec::new(); + let mut buf = [0_u8; 4096]; + loop { + if let Some(out) = answer(&seen) { + let _ = s.write_all(&out); + let _ = s.flush(); + s.close(); + return; + } + match s.read(&mut buf) { + Ok(0) | Err(_) => return, + Ok(n) => seen.extend_from_slice(&buf[..n]), + } + } +} + +// ---- the host's own proof, run with the suite ---- + +const OWNER: InstanceId = InstanceId(7); + +fn need(transport: &str, class: u32) -> ReadNeed { + ReadNeed { + direction: DIRECTION_OUTBOUND, + egress_class: class, + transport: transport.to_owned(), + auth: String::new(), + target_from: String::new(), + trust_from: String::new(), + details: ReadBlob { + fmt: 0, + flags: 0, + bytes: Vec::new(), + }, + timeout_ms: 0, + } +} + +/// `f` until it answers other than PENDING, as a plugin's re-entries on its ticket would. +fn settle(mut f: impl FnMut() -> Result) -> Result { + let until = Instant::now() + Duration::from_secs(10); + loop { + match f() { + Err(ConnError::Pending) if Instant::now() < until => { + std::thread::sleep(Duration::from_millis(2)); + } + answered => return answered, + } + } +} + +/// Read `id` to its completion (or `want` body bytes): its fields pieces' count and its body. +fn drain(c: &dyn DeclaredConns, id: ConnId, want: usize) -> (usize, Vec) { + let (mut fields, mut body) = (0, Vec::new()); + let mut buf = [0_u8; 256]; + while body.len() < want { + let Ok(p) = settle(|| c.read(OWNER, id, NO_TICKET, &mut buf)) else { + break; + }; + match p.kind { + PieceKind::Fields => fields += 1, + PieceKind::Body => body.extend_from_slice(&buf[..p.len]), + PieceKind::Completion => break, + PieceKind::HookReply => {} + } + } + (fields, body) +} + +/// Five bytes back for five bytes in: the TLS echo the host's own proof dials. +fn echo(seen: &[u8]) -> Option> { + (seen.len() >= 5).then(|| seen[..5].to_vec()) +} + +/// A raw `tcp` stream to a TLS echo, upgraded through the host's TLS: what came back. +fn upgraded_echo(c: &dyn DeclaredConns, far: &str) -> Result, ConnError> { + c.declare( + OWNER, + NeedId(0), + &need("tcp", EGRESS_OPERATOR_INFRASTRUCTURE), + None, + None, + )?; + let id = settle(|| { + c.open( + OWNER, + NeedId(0), + &OpenDesc { + target: far, + timeout_ms: 5_000, + ..OpenDesc::default() + }, + ) + })?; + settle(|| c.upgrade_secure(OWNER, id, Some("localhost"), None, false, NO_TICKET))?; + let mut at = 0; + while at < 5 { + at += settle(|| c.write(OWNER, id, &b"hello"[at..], false, false))?; + } + let (_, body) = drain(c, id, 5); + let _ = c.close(OWNER, id); + Ok(body) +} + +/// A TLS echo on a port of its own; its address. +fn tls_echo() -> String { + let listener = TcpListener::bind("127.0.0.1:0").expect("a local listener"); + let at = listener.local_addr().expect("its address").to_string(); + serve(listener, echo); + at +} + +/// THE HOST'S TLS TRUSTS THE SUITE'S TEST ANCHORS: a stream to a far end whose certificate chains +/// to the test CA is upgraded and round-trips (the anchors went to the host, never to the plugin). +#[test] +fn the_hosts_tls_upgrade_verifies_against_the_suites_test_anchors() { + let c = host(Arc::new(|_| {}), Some(anchors())); + assert_eq!( + upgraded_echo(c.as_ref(), &tls_echo()), + Ok(b"hello".to_vec()) + ); +} + +/// RED: the same upgrade with the anchors withheld is refused: the platform roots alone do not +/// trust the test CA. +#[test] +fn red_with_the_anchors_withheld_the_hosts_tls_upgrade_is_refused() { + let c = host(Arc::new(|_| {}), None); + let answer = upgraded_echo(c.as_ref(), &tls_echo()); + assert!(answer.is_err(), "upgraded over an untrusted CA: {answer:?}"); +} + +/// AN `http` NEED THROUGH THE HOST'S FRAMER: declared on the host, opened at a local HTTP +/// listener's URL, the request goes out framed by the linked http door over the tcp carrier and the +/// answer comes back as one head and its body. +#[test] +fn an_http_need_reaches_a_local_http_listener_through_the_hosts_framer() { + use busbar_contract::abi::host::conn::connector::EGRESS_LOOPBACK_ALLOWED; + + let listener = TcpListener::bind("127.0.0.1:0").expect("a local listener"); + let at = listener.local_addr().expect("its address"); + let far = std::thread::spawn(move || { + let (mut s, _) = listener.accept().expect("the host dials it"); + let mut seen = Vec::new(); + let mut buf = [0_u8; 512]; + while !seen.windows(4).any(|w| w == b"\r\n\r\n") { + let n = s.read(&mut buf).expect("the request"); + assert!(n > 0, "the request ended early"); + seen.extend_from_slice(&buf[..n]); + } + s.write_all(b"HTTP/1.1 200 OK\r\ncontent-length: 5\r\n\r\nhello") + .expect("the answer"); + String::from_utf8_lossy(&seen).into_owned() + }); + + let c = host(Arc::new(|_| {}), None); + assert!(c.serves_scheme("http"), "the host serves http"); + c.declare( + OWNER, + NeedId(0), + &need("http", EGRESS_LOOPBACK_ALLOWED), + None, + None, + ) + .expect("the http need is declared"); + let target = format!("http://{at}/v1/probe"); + let id = settle(|| { + c.open( + OWNER, + NeedId(0), + &OpenDesc { + target: &target, + method: b"GET", + head_target: b"/v1/probe", + timeout_ms: 5_000, + ..OpenDesc::default() + }, + ) + }) + .expect("the need opens through the framer"); + let (fields, body) = drain(c.as_ref(), id, 5); + let seen = far.join().expect("the listener answered"); + assert!(seen.starts_with("GET /v1/probe HTTP/1.1\r\n"), "{seen}"); + assert_eq!(fields, 1, "one head"); + assert_eq!(body, b"hello"); + c.close(OWNER, id).expect("closed"); +} diff --git a/export-webhook/declares.json b/export-webhook/declares.json index cf70cbb..c94344c 100644 --- a/export-webhook/declares.json +++ b/export-webhook/declares.json @@ -38,5 +38,8 @@ "action": "If logs are being lost, check the webhook sink's reachability and the delivery counters. `busbar_webhook_logs_dropped_total` tracks the volume.", "since": "1.6.0" } + ], + "needs": [ + "http" ] } From 2ec85bce3c9598386c079391b227a6407c4c566f Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Mon, 5 Oct 2026 09:08:18 -0700 Subject: [PATCH 2/3] repin to busbar lane-p4-fleet-doors daf4c0275e (pin-check holds busbar's source exactly and each transport framer to busbar's lock); re-rendered with busbar-release #162, Cargo.lock re-resolved from busbar's lock at the pin --- .busbar-ref | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/repin.yml | 2 +- Cargo.lock | 22 +++++++++++----------- Cargo.toml | 16 ++++++++-------- deny.toml | 2 +- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.busbar-ref b/.busbar-ref index a43f758..a483331 100644 --- a/.busbar-ref +++ b/.busbar-ref @@ -1 +1 @@ -324e30d2b0725c9dc8538580b691a487b336a954 1.6.0 +daf4c0275e734fe1988053e241486042351b8fb3 1.6.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8c428f..2a0da25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ permissions: jobs: ci: - uses: GetBusbar/busbar/.github/workflows/plugin-ci.yml@324e30d2b0725c9dc8538580b691a487b336a954 + uses: GetBusbar/busbar/.github/workflows/plugin-ci.yml@daf4c0275e734fe1988053e241486042351b8fb3 with: service: none busbar_checkout: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 328b1f0..1cd835e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: secrets: inherit release: needs: ci - uses: GetBusbar/busbar/.github/workflows/plugin-release.yml@324e30d2b0725c9dc8538580b691a487b336a954 + uses: GetBusbar/busbar/.github/workflows/plugin-release.yml@daf4c0275e734fe1988053e241486042351b8fb3 with: plugin_crate: busbar-export-webhook-plugin manifest_name: busbar-export-webhook @@ -41,7 +41,7 @@ jobs: consumer-verify: needs: release if: ${{ !cancelled() }} - uses: GetBusbar/busbar/.github/workflows/plugin-consumer-verify.yml@324e30d2b0725c9dc8538580b691a487b336a954 + uses: GetBusbar/busbar/.github/workflows/plugin-consumer-verify.yml@daf4c0275e734fe1988053e241486042351b8fb3 with: version: ${{ github.ref_name }} asset_prefix: busbar-export-webhook diff --git a/.github/workflows/repin.yml b/.github/workflows/repin.yml index ceb72f0..d537269 100644 --- a/.github/workflows/repin.yml +++ b/.github/workflows/repin.yml @@ -28,7 +28,7 @@ permissions: jobs: repin: - uses: GetBusbar/busbar/.github/workflows/plugin-repin.yml@324e30d2b0725c9dc8538580b691a487b336a954 + uses: GetBusbar/busbar/.github/workflows/plugin-repin.yml@daf4c0275e734fe1988053e241486042351b8fb3 with: busbar_sha: ${{ github.event.client_payload.sha || inputs.busbar_sha }} busbar_version: ${{ github.event.client_payload.version || inputs.busbar_version }} diff --git a/Cargo.lock b/Cargo.lock index 3e843c9..66c3a0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,7 +210,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "busbar-contract" version = "1.6.0" -source = "git+https://www.github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://www.github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "async-trait", "base64 0.22.1", @@ -233,7 +233,7 @@ dependencies = [ [[package]] name = "busbar-core-connector" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "busbar-kernel", @@ -282,7 +282,7 @@ dependencies = [ [[package]] name = "busbar-kernel" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "arc-swap", "async-trait", @@ -332,7 +332,7 @@ dependencies = [ [[package]] name = "busbar-kernel-audit" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "ed25519-dalek", @@ -343,7 +343,7 @@ dependencies = [ [[package]] name = "busbar-kernel-breaker" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "httpdate", @@ -352,7 +352,7 @@ dependencies = [ [[package]] name = "busbar-kernel-egress" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "bytes", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "busbar-kernel-identity" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "hex", @@ -374,7 +374,7 @@ dependencies = [ [[package]] name = "busbar-kernel-ledger" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "ring", @@ -384,7 +384,7 @@ dependencies = [ [[package]] name = "busbar-kernel-scope" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", ] @@ -392,7 +392,7 @@ dependencies = [ [[package]] name = "busbar-kernel-wal" version = "1.6.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "ring", @@ -401,7 +401,7 @@ dependencies = [ [[package]] name = "busbar-plugin-loader" version = "1.5.0" -source = "git+https://github.com/GetBusbar/busbar?rev=324e30d2b0725c9dc8538580b691a487b336a954#324e30d2b0725c9dc8538580b691a487b336a954" +source = "git+https://github.com/GetBusbar/busbar?rev=daf4c0275e734fe1988053e241486042351b8fb3#daf4c0275e734fe1988053e241486042351b8fb3" dependencies = [ "busbar-contract", "busbar-kernel-ledger", diff --git a/Cargo.toml b/Cargo.toml index 931d029..dbfcb22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ # `.busbar-ref`; no sibling-checkout path dependency ships in any manifest. # # THIRD-PARTY VERSIONS ARE THE FLEET'S, NOT THIS REPO'S. The table below is busbar's own root -# `[workspace.dependencies]` (third-party rows) at busbar 324e30d2b0725c9dc8538580b691a487b336a954, followed by the plugin-only rows -# of busbar's `.github/fleet/deps.toml` at 324e30d2b0725c9dc8538580b691a487b336a954. A member takes a crate with +# `[workspace.dependencies]` (third-party rows) at busbar daf4c0275e734fe1988053e241486042351b8fb3, followed by the plugin-only rows +# of busbar's `.github/fleet/deps.toml` at daf4c0275e734fe1988053e241486042351b8fb3. A member takes a crate with # `{ workspace = true }` (adding features if it needs them); a crate in neither table is a new # `deps.toml` row in busbar first. CI holds this repo's Cargo.lock to busbar's lock at the pin. [workspace] @@ -29,15 +29,15 @@ publish = false repository = "https://github.com/GetBusbar/busbar-export-webhook" [workspace.dependencies] -busbar-contract = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } -busbar-plugin-loader = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } +busbar-contract = { git = "https://github.com/GetBusbar/busbar", rev = "daf4c0275e734fe1988053e241486042351b8fb3" } +busbar-plugin-loader = { git = "https://github.com/GetBusbar/busbar", rev = "daf4c0275e734fe1988053e241486042351b8fb3" } # THE SUITE'S HOST CONNECTOR (dev-only; export-webhook-plugin/tests/support/conformance_host.rs, # rendered because the declares file states network needs): busbar's connector and its TLS # test kit at the pin, and the transport framers those needs name, at the revs busbar links. -busbar-core-connector = { git = "https://github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954", features = ["test-support"] } +busbar-core-connector = { git = "https://github.com/GetBusbar/busbar", rev = "daf4c0275e734fe1988053e241486042351b8fb3", features = ["test-support"] } busbar-transport-http = { git = "https://github.com/GetBusbar/busbar-transport-http", rev = "fc91230af97997994e9206124ee7414f3aec6eee" } busbar-transport-tcp = { git = "https://github.com/GetBusbar/busbar-transport-tcp", rev = "89d08ebcb91e5b2d4001b667fba151d9bc09d22d" } -# busbar's root [workspace.dependencies], third-party rows, at 324e30d2b0725c9dc8538580b691a487b336a954 +# busbar's root [workspace.dependencies], third-party rows, at daf4c0275e734fe1988053e241486042351b8fb3 a2a-lf = "0.3.0" a2a-pb = "0.2.0" arc-swap = "1" @@ -113,7 +113,7 @@ url = "2" webpki = { package = "rustls-webpki", version = "0.103", default-features = false, features = ["std", "ring"] } webpki-roots = "1" zeroize = "1" -# busbar .github/fleet/deps.toml [plugin-deps], at 324e30d2b0725c9dc8538580b691a487b336a954 +# busbar .github/fleet/deps.toml [plugin-deps], at daf4c0275e734fe1988053e241486042351b8fb3 ldap3 = { version = "0.12", default-features = false, features = ["sync"] } mysql = { version = "28", default-features = false, features = ["minimal-rust"] } mysql_common = { version = "0.35", default-features = false } @@ -128,4 +128,4 @@ ulid = "1" # patches them to its own tree. The source is busbar spelled through www.github.com: Cargo # refuses a patch that names the source it patches. [patch."https://github.com/GetBusbar/busbar"] -busbar-contract = { git = "https://www.github.com/GetBusbar/busbar", rev = "324e30d2b0725c9dc8538580b691a487b336a954" } +busbar-contract = { git = "https://www.github.com/GetBusbar/busbar", rev = "daf4c0275e734fe1988053e241486042351b8fb3" } diff --git a/deny.toml b/deny.toml index c6a1b83..f931e1d 100644 --- a/deny.toml +++ b/deny.toml @@ -1,5 +1,5 @@ # RENDERED by `busbar-release plugin sync` from GetBusbar/busbar-release template/ and busbar's -# `.github/fleet/deps.toml` at 324e30d2b0725c9dc8538580b691a487b336a954; a hand edit is overwritten by the next sync. CI runs +# `.github/fleet/deps.toml` at daf4c0275e734fe1988053e241486042351b8fb3; a hand edit is overwritten by the next sync. CI runs # `cargo deny check` on it (busbar's plugin-ci.yml at the pin). The license allowlist is busbar's own; # the one reviewed git source is busbar itself, at the pin. [graph] From 8a437985d42e7d8cb462bb9c815c0dbc20a4b59e Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Mon, 5 Oct 2026 09:19:12 -0700 Subject: [PATCH 3/3] re-render with busbar-release #162 at f0d23cb (the conformance host's TLS front for in-band StartTLS protocols) --- .../tests/support/conformance_host.rs | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/export-webhook-plugin/tests/support/conformance_host.rs b/export-webhook-plugin/tests/support/conformance_host.rs index 28ceebf..3687e06 100644 --- a/export-webhook-plugin/tests/support/conformance_host.rs +++ b/export-webhook-plugin/tests/support/conformance_host.rs @@ -44,7 +44,7 @@ #![allow(dead_code)] use std::io::{Read, Write}; -use std::net::{SocketAddr, TcpListener, ToSocketAddrs}; +use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs}; use std::sync::{Arc, OnceLock}; use std::time::{Duration, Instant}; @@ -324,6 +324,89 @@ fn reply(s: &mut StdServerSession, answer: Answer) { } } +/// A far end's cleartext negotiation before TLS (a protocol's own StartTLS: Postgres's +/// `SSLRequest` answered `S`, LDAP's StartTLS extended operation, ...): `true` = go on to TLS. +pub type Preamble = fn(&mut TcpStream) -> bool; + +/// THE SUITE'S TLS FRONT at [`FAR_END`] (started once; later calls are no-ops): each connection's +/// cleartext `preamble` runs, then the TLS handshake (busbar's test kit, a `localhost` certificate +/// [`anchors`] trusts), then its bytes are carried both ways to the REAL backend at `upstream` +/// (the plugin's live service, in the clear on loopback). What it proves: the plugin's own +/// connection is secured by the HOST's TLS against the suite's anchors. +/// +/// # Panics +/// [`FAR_END`] cannot be bound. +pub fn tls_front(preamble: Preamble, upstream: &'static str) { + static STARTED: OnceLock<()> = OnceLock::new(); + STARTED.get_or_init(|| { + let listener = TcpListener::bind(FAR_END) + .unwrap_or_else(|e| panic!("the suite's TLS front cannot bind {FAR_END}: {e}")); + let tls = ServerTls::new(&[ca().leaf_der.clone()], &ca().key_der, None, &[]) + .unwrap_or_else(|e| panic!("the suite's TLS front has no TLS identity: {e}")); + std::thread::spawn(move || { + for tcp in listener.incoming() { + let Ok(tcp) = tcp else { return }; + let tls = tls.clone(); + std::thread::spawn(move || front(tcp, &tls, preamble, upstream)); + } + }); + }); +} + +/// One connection through the TLS front: preamble, handshake, then both directions carried until +/// either side ends. +fn front(mut tcp: TcpStream, tls: &ServerTls, preamble: Preamble, upstream: &str) { + if !preamble(&mut tcp) { + return; + } + let Ok(ctl) = tcp.try_clone() else { return }; + let Ok(mut s) = tls.accept_std(tcp) else { + return; + }; + if !s.handshake_ok() { + return; + } + let Ok(mut up) = TcpStream::connect(upstream) else { + return; + }; + let tick = Some(Duration::from_millis(2)); + if ctl.set_read_timeout(tick).is_err() || up.set_read_timeout(tick).is_err() { + return; + } + let idle = |e: &std::io::Error| { + matches!( + e.kind(), + std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut + ) + }; + let mut buf = [0_u8; 16 * 1024]; + loop { + match s.read(&mut buf) { + Ok(0) => return, + Ok(n) => { + if up.write_all(&buf[..n]).is_err() { + return; + } + } + Err(e) if idle(&e) => {} + Err(_) => return, + } + match up.read(&mut buf) { + Ok(0) => { + s.close(); + return; + } + Ok(n) => { + if s.write_all(&buf[..n]).and_then(|()| s.flush()).is_err() { + return; + } + } + Err(e) if idle(&e) => {} + Err(_) => return, + } + } +} + // ---- the host's own proof, run with the suite ---- const OWNER: InstanceId = InstanceId(7);