You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iggy.apache.org by gk...@apache.org on 2026/09/08 16:42:39 UTC

(iggy) branch master updated: feat(connectors): add RabbitMQ sink (#3973)

This is an automated email from the ASF dual-hosted git repository.

numinnex pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e3823196 feat(connectors): add RabbitMQ sink (#3973)
2e3823196 is described below

commit 2e38231960f4d3805ca72d8279d3e95557936ede
Author: Amrit <25...@users.noreply.github.com>
AuthorDate: Tue Sep 8 09:42:35 2026 -0700

    feat(connectors): add RabbitMQ sink (#3973)
    
    Replaces #3811 (could not be reopened after rebasing onto master).
    Rebased to current master and addressed all review comments.
    
    Relates to #3747
    
    Adds the RabbitMQ sink connector via the lapin client. Source will be a
    separate PR.
---
 .github/workflows/_build_rust_artifacts.yml        |    2 +-
 .github/workflows/edge-release.yml                 |    1 +
 Cargo.lock                                         | 1495 ++++++++++++++------
 Cargo.toml                                         |    2 +
 core/connectors/README.md                          |    1 +
 .../example_config/connectors/rabbitmq_sink.toml   |   46 +
 core/connectors/sinks/README.md                    |    1 +
 core/connectors/sinks/rabbitmq_sink/Cargo.toml     |   51 +
 core/connectors/sinks/rabbitmq_sink/README.md      |   50 +
 core/connectors/sinks/rabbitmq_sink/config.toml    |   46 +
 core/connectors/sinks/rabbitmq_sink/src/lib.rs     |  783 ++++++++++
 core/integration/Cargo.toml                        |    1 +
 core/integration/tests/connectors/fixtures/mod.rs  |    6 +
 .../connectors/fixtures/rabbitmq/container.rs      |  327 +++++
 .../tests/connectors/fixtures/rabbitmq/mod.rs      |   26 +
 .../tests/connectors/fixtures/rabbitmq/sink.rs     |  273 ++++
 core/integration/tests/connectors/mod.rs           |    1 +
 core/integration/tests/connectors/rabbitmq/mod.rs  |   18 +
 .../tests/connectors/rabbitmq/rabbitmq_sink.rs     |  429 ++++++
 .../tests/connectors/rabbitmq/sink.toml            |   20 +
 scripts/bump-version.sh                            |    2 +-
 21 files changed, 3123 insertions(+), 458 deletions(-)

diff --git a/.github/workflows/_build_rust_artifacts.yml b/.github/workflows/_build_rust_artifacts.yml
index bd56b1071..a1592ad78 100644
--- a/.github/workflows/_build_rust_artifacts.yml
+++ b/.github/workflows/_build_rust_artifacts.yml
@@ -46,7 +46,7 @@ on:
       connector_plugins:
         type: string
         required: false
-        default: "iggy_connector_elasticsearch_sink,iggy_connector_elasticsearch_source,iggy_connector_iceberg_sink,iggy_connector_postgres_sink,iggy_connector_postgres_source,iggy_connector_quickwit_sink,iggy_connector_random_source,iggy_connector_s3_sink,iggy_connector_stdout_sink,iggy_connector_surrealdb_sink"
+        default: "iggy_connector_elasticsearch_sink,iggy_connector_elasticsearch_source,iggy_connector_iceberg_sink,iggy_connector_postgres_sink,iggy_connector_postgres_source,iggy_connector_quickwit_sink,iggy_connector_random_source,iggy_connector_s3_sink,iggy_connector_stdout_sink,iggy_connector_surrealdb_sink, iggy_connector_rabbitmq_sink"
         description: "Comma-separated list of connector plugin crates to build as shared libraries"
     outputs:
       artifact_name:
diff --git a/.github/workflows/edge-release.yml b/.github/workflows/edge-release.yml
index 2514c3227..7dde3b719 100644
--- a/.github/workflows/edge-release.yml
+++ b/.github/workflows/edge-release.yml
@@ -105,6 +105,7 @@ jobs:
             - `iggy_connector_s3_sink`
             - `iggy_connector_stdout_sink`
             - `iggy_connector_surrealdb_sink`
+            - `iggy_connector_rabbitmq_sink`
 
             ## Downloads
 
diff --git a/Cargo.lock b/Cargo.lock
index 7856dd413..98b0f147d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 4
 
 [[package]]
 name = "actix-codec"
-version = "0.5.3"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31404e1443b7b7bcaa311c1af456775cc3f668e34573f1503d7ce4844327629e"
+checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
 dependencies = [
  "bitflags 2.13.1",
  "bytes",
@@ -59,12 +59,11 @@ dependencies = [
 
 [[package]]
 name = "actix-http"
-version = "3.13.3"
+version = "3.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11004b0e9b44b4eb3d15e0c3132b96fb178c7e50a74758b2f17bb9cc9a7fb4f6"
+checksum = "86d62d1a48894ec9450bcde7ef1e3681205771ff6ea9c61cc5ae031145192787"
 dependencies = [
  "actix-codec",
- "actix-rt",
  "actix-service",
  "actix-utils",
  "base64 0.22.1",
@@ -123,9 +122,9 @@ dependencies = [
 
 [[package]]
 name = "actix-rt"
-version = "2.13.0"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a16bf2f19c2ad84842bdfe6f3665620e93197d5c607889bfa3aaac45e762fd1"
+checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63"
 dependencies = [
  "futures-core",
  "tokio",
@@ -143,7 +142,7 @@ dependencies = [
  "futures-core",
  "futures-util",
  "mio",
- "socket2",
+ "socket2 0.6.5",
  "tokio",
  "tracing",
 ]
@@ -205,7 +204,7 @@ dependencies = [
  "serde_json",
  "serde_urlencoded",
  "smallvec",
- "socket2",
+ "socket2 0.6.5",
  "time",
  "tracing",
  "url",
@@ -235,7 +234,7 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
 dependencies = [
- "crypto-common 0.1.6",
+ "crypto-common 0.1.7",
  "generic-array",
 ]
 
@@ -262,13 +261,13 @@ dependencies = [
 
 [[package]]
 name = "aes"
-version = "0.9.3"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32"
+checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138"
 dependencies = [
  "cipher 0.5.2",
  "cpubits",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
 ]
 
 [[package]]
@@ -292,7 +291,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f"
 dependencies = [
  "aead 0.6.1",
- "aes 0.9.3",
+ "aes 0.9.1",
  "cipher 0.5.2",
  "ctr 0.10.1",
  "ctutils",
@@ -327,9 +326,9 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "1.1.5"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
 dependencies = [
  "memchr",
 ]
@@ -379,11 +378,59 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
+[[package]]
+name = "amq-protocol"
+version = "7.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "587d313f3a8b4a40f866cc84b6059fe83133bf172165ac3b583129dd211d8e1c"
+dependencies = [
+ "amq-protocol-tcp",
+ "amq-protocol-types",
+ "amq-protocol-uri",
+ "cookie-factory",
+ "nom 7.1.3",
+ "serde",
+]
+
+[[package]]
+name = "amq-protocol-tcp"
+version = "7.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc707ab9aa964a85d9fc25908a3fdc486d2e619406883b3105b48bf304a8d606"
+dependencies = [
+ "amq-protocol-uri",
+ "tcp-stream",
+ "tracing",
+]
+
+[[package]]
+name = "amq-protocol-types"
+version = "7.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf99351d92a161c61ec6ecb213bc7057f5b837dd4e64ba6cb6491358efd770c4"
+dependencies = [
+ "cookie-factory",
+ "nom 7.1.3",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "amq-protocol-uri"
+version = "7.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f89f8273826a676282208e5af38461a07fe939def57396af6ad5997fcf56577d"
+dependencies = [
+ "amq-protocol-types",
+ "percent-encoding",
+ "url",
+]
+
 [[package]]
 name = "android_system_properties"
-version = "0.1.6"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
 dependencies = [
  "libc",
 ]
@@ -503,14 +550,14 @@ checksum = "2b350bfd03649e07aa05c0a81b3e15934374e585c98204a57e20b9d49f49bb9a"
 dependencies = [
  "keyring-core",
  "log",
- "security-framework",
+ "security-framework 3.7.0",
 ]
 
 [[package]]
 name = "ar_archive_writer"
-version = "0.5.3"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73cd58deff2140a0a8eae87e417bd01db68a33e148aa93d1e8cd837e55e312b6"
+checksum = "4087686b4b0a3427190bae57a1d9a478dbb2d40c5dc1bd6e2b6d797913bdd348"
 dependencies = [
  "object",
 ]
@@ -549,7 +596,7 @@ checksum = "134c52ddac6d63c576bef8168db10c83c49c26444ecbc68060fef078925a901c"
 dependencies = [
  "base64ct",
  "blake2",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
  "password-hash",
 ]
 
@@ -714,7 +761,7 @@ dependencies = [
  "arrow-select",
  "chrono",
  "half",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "itoa",
  "lexical-core",
  "memchr",
@@ -894,7 +941,7 @@ version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
 dependencies = [
- "event-listener",
+ "event-listener 5.4.1",
  "event-listener-strategy",
  "futures-core",
  "pin-project-lite",
@@ -914,9 +961,9 @@ dependencies = [
 
 [[package]]
 name = "async-compression"
-version = "0.4.43"
+version = "0.4.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3976abdc8fe7d1133d43d304afd42abdf5bc3e1319d263d223bde07b5efc4be8"
+checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac"
 dependencies = [
  "compression-codecs",
  "compression-core",
@@ -972,12 +1019,57 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
 dependencies = [
  "async-task",
  "concurrent-queue",
- "fastrand",
- "futures-lite",
+ "fastrand 2.5.0",
+ "futures-lite 2.6.1",
  "pin-project-lite",
  "slab",
 ]
 
+[[package]]
+name = "async-global-executor"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13f937e26114b93193065fd44f507aa2e9169ad0cdabbb996920b1fe1ddea7ba"
+dependencies = [
+ "async-channel",
+ "async-executor",
+ "async-io 2.6.0",
+ "async-lock 3.4.2",
+ "blocking",
+ "futures-lite 2.6.1",
+]
+
+[[package]]
+name = "async-global-executor-trait"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9af57045d58eeb1f7060e7025a1631cbc6399e0a1d10ad6735b3d0ea7f8346ce"
+dependencies = [
+ "async-global-executor",
+ "async-trait",
+ "executor-trait",
+]
+
+[[package]]
+name = "async-io"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
+dependencies = [
+ "async-lock 2.8.0",
+ "autocfg",
+ "cfg-if",
+ "concurrent-queue",
+ "futures-lite 1.13.0",
+ "log",
+ "parking",
+ "polling 2.8.0",
+ "rustix 0.37.28",
+ "slab",
+ "socket2 0.4.10",
+ "waker-fn",
+]
+
 [[package]]
 name = "async-io"
 version = "2.6.0"
@@ -988,21 +1080,30 @@ dependencies = [
  "cfg-if",
  "concurrent-queue",
  "futures-io",
- "futures-lite",
+ "futures-lite 2.6.1",
  "parking",
- "polling",
+ "polling 3.11.0",
  "rustix 1.1.4",
  "slab",
  "windows-sys 0.61.2",
 ]
 
+[[package]]
+name = "async-lock"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
+dependencies = [
+ "event-listener 2.5.3",
+]
+
 [[package]]
 name = "async-lock"
 version = "3.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
 dependencies = [
- "event-listener",
+ "event-listener 5.4.1",
  "event-listener-strategy",
  "pin-project-lite",
 ]
@@ -1014,17 +1115,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
 dependencies = [
  "async-channel",
- "async-io",
- "async-lock",
+ "async-io 2.6.0",
+ "async-lock 3.4.2",
  "async-signal",
  "async-task",
  "blocking",
  "cfg-if",
- "event-listener",
- "futures-lite",
+ "event-listener 5.4.1",
+ "futures-lite 2.6.1",
  "rustix 1.1.4",
 ]
 
+[[package]]
+name = "async-reactor-trait"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6012d170ad00de56c9ee354aef2e358359deb1ec504254e0e5a3774771de0e"
+dependencies = [
+ "async-io 1.13.0",
+ "async-trait",
+ "futures-core",
+ "reactor-trait",
+]
+
 [[package]]
 name = "async-recursion"
 version = "1.1.1"
@@ -1053,8 +1166,8 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
 dependencies = [
- "async-io",
- "async-lock",
+ "async-io 2.6.0",
+ "async-lock 3.4.2",
  "atomic-waker",
  "cfg-if",
  "futures-core",
@@ -1101,7 +1214,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -1129,7 +1242,7 @@ dependencies = [
  "async-compression",
  "binrw",
  "crc32fast",
- "futures-lite",
+ "futures-lite 2.6.1",
  "pin-project",
  "thiserror 2.0.20",
  "tokio",
@@ -1245,9 +1358,9 @@ dependencies = [
 
 [[package]]
 name = "aws-config"
-version = "1.11.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a767267da9e2c2e189b2f9df8b5657e850ecf5352644734ba130d4a57095cf1b"
+checksum = "47712fde1909402600ccfbb26e47d482d2e58bb9e9e603d9f17e67cc435a6319"
 dependencies = [
  "aws-credential-types",
  "aws-runtime",
@@ -1263,7 +1376,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-types",
  "bytes",
- "fastrand",
+ "fastrand 2.5.0",
  "hex",
  "http 1.5.0",
  "sha1 0.10.7",
@@ -1338,9 +1451,9 @@ dependencies = [
 
 [[package]]
 name = "aws-runtime"
-version = "1.9.1"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9007227e10b5fed2f3e0a2beff489211e2b5604c400b7a9d5d81ca9d64c24bb"
+checksum = "7816e98ee912159f45d307e5ee6bfea4a335a55aee15f7f3e32f81a6f3000f1d"
 dependencies = [
  "aws-credential-types",
  "aws-sigv4",
@@ -1352,7 +1465,7 @@ dependencies = [
  "aws-types",
  "bytes",
  "bytes-utils",
- "fastrand",
+ "fastrand 2.5.0",
  "http 1.5.0",
  "http-body 1.1.0",
  "percent-encoding",
@@ -1363,9 +1476,9 @@ dependencies = [
 
 [[package]]
 name = "aws-sdk-dynamodb"
-version = "1.123.0"
+version = "1.117.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcd10d92058d5da989a7838fd09d70e9457390a81ba672abf5685099f3562bce"
+checksum = "0f2b4adcf6592e06ebb2c78235ae09cee178263a5b7fc20ae5ea07ca67067bb6"
 dependencies = [
  "arc-swap",
  "aws-credential-types",
@@ -1380,19 +1493,18 @@ dependencies = [
  "aws-smithy-types",
  "aws-types",
  "bytes",
- "fastrand",
+ "fastrand 2.5.0",
  "http 0.2.12",
  "http 1.5.0",
  "regex-lite",
  "tracing",
- "url",
 ]
 
 [[package]]
 name = "aws-sdk-sso"
-version = "1.108.0"
+version = "1.103.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c15301b04372832947916607983b114b3374b9db0be058a00fb7513800de1f05"
+checksum = "0469f435f645ad2162cfb463b15bde37115966ee3acf2d87fb4871ee309b8401"
 dependencies = [
  "arc-swap",
  "aws-credential-types",
@@ -1407,7 +1519,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-types",
  "bytes",
- "fastrand",
+ "fastrand 2.5.0",
  "http 0.2.12",
  "http 1.5.0",
  "regex-lite",
@@ -1416,9 +1528,9 @@ dependencies = [
 
 [[package]]
 name = "aws-sdk-ssooidc"
-version = "1.110.0"
+version = "1.105.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72cc2c205cb27108183cf1856333f7d584c2ba0f505421b4209ca5828f9ea899"
+checksum = "085faefb253f770655e162b9304321e62a1e71adf7f019ee1f4454228a377b3a"
 dependencies = [
  "arc-swap",
  "aws-credential-types",
@@ -1433,7 +1545,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-types",
  "bytes",
- "fastrand",
+ "fastrand 2.5.0",
  "http 0.2.12",
  "http 1.5.0",
  "regex-lite",
@@ -1442,9 +1554,9 @@ dependencies = [
 
 [[package]]
 name = "aws-sdk-sts"
-version = "1.113.0"
+version = "1.108.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68182ecb449f7537db0f4d5d25917789cf41e32074a9fe47b6a0b847fe1d2032"
+checksum = "3c72b08911d8128dd360fe1b22a9fec0fa8b552dde8ec828dcf20ef5ec974e9f"
 dependencies = [
  "arc-swap",
  "aws-credential-types",
@@ -1460,7 +1572,7 @@ dependencies = [
  "aws-smithy-types",
  "aws-smithy-xml",
  "aws-types",
- "fastrand",
+ "fastrand 2.5.0",
  "http 0.2.12",
  "http 1.5.0",
  "regex-lite",
@@ -1523,21 +1635,21 @@ dependencies = [
 
 [[package]]
 name = "aws-smithy-http-client"
-version = "1.4.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebfd138fac0337cee7516c352757ea73b9f2266e57d0bcb5bc70e9547e45aef1"
+checksum = "635d23afda0a6ab48d666c4d447c4873e8d1e83518a2be2093122397e50b838e"
 dependencies = [
  "aws-smithy-async",
  "aws-smithy-runtime-api",
  "aws-smithy-types",
- "h2 0.4.19",
+ "h2 0.4.15",
  "http 1.5.0",
  "hyper",
  "hyper-rustls",
  "hyper-util",
  "pin-project-lite",
  "rustls",
- "rustls-native-certs",
+ "rustls-native-certs 0.8.4",
  "rustls-pki-types",
  "tokio",
  "tokio-rustls",
@@ -1567,22 +1679,19 @@ dependencies = [
 
 [[package]]
 name = "aws-smithy-query"
-version = "0.62.0"
+version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512346c7212ab7436df2d77a16d976a468ae44a418835511d2a69269810aaf62"
+checksum = "dd22a6ba36e3f113cb8d5b3d1fe0ed31c76ee608ef63322d753bb8d2c9479e77"
 dependencies = [
- "aws-smithy-runtime-api",
- "aws-smithy-schema",
  "aws-smithy-types",
- "aws-smithy-xml",
  "urlencoding",
 ]
 
 [[package]]
 name = "aws-smithy-runtime"
-version = "1.14.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b82e438d30e02a825d363bd639a9efaed68a8089d86101054b0081e7e0d3e606"
+checksum = "bea94a9ff8464016338c851e24b472d7131c388c88898a502e781815b2ee6045"
 dependencies = [
  "aws-smithy-async",
  "aws-smithy-http",
@@ -1592,7 +1701,7 @@ dependencies = [
  "aws-smithy-schema",
  "aws-smithy-types",
  "bytes",
- "fastrand",
+ "fastrand 2.5.0",
  "http 0.2.12",
  "http 1.5.0",
  "http-body 0.4.6",
@@ -1606,9 +1715,9 @@ dependencies = [
 
 [[package]]
 name = "aws-smithy-runtime-api"
-version = "1.15.0"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "954c563ce84507722d2679f07a35d21b9c6466b3872d513020d0281fc8112ac9"
+checksum = "22ed1ebe6e0a95ea84570225f5a8208dec4b8f77e61a9b0d6f51773fcb4612f0"
 dependencies = [
  "aws-smithy-async",
  "aws-smithy-runtime-api-macros",
@@ -1646,9 +1755,9 @@ dependencies = [
 
 [[package]]
 name = "aws-smithy-types"
-version = "1.6.2"
+version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fce83ce9abbb198d25bc7131e468d0f9fe1257125e58c39f3f9fc9f5098c9647"
+checksum = "d6dc683efb34b9e755675b37fedbe0103141e5b6df7bdc9eb6967756a8c167d8"
 dependencies = [
  "base64-simd",
  "bytes",
@@ -1672,9 +1781,9 @@ dependencies = [
 
 [[package]]
 name = "aws-smithy-xml"
-version = "0.62.0"
+version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce84f71c72fee2cbbadde6e7d082f5fb466e3a84733855295fa7aafd1b31b7d8"
+checksum = "ea3f68eec3607f02acd24067969ce2abc6ba16aa7d5ce59ca450ed2fb5f78957"
 dependencies = [
  "aws-smithy-runtime-api",
  "aws-smithy-schema",
@@ -1684,9 +1793,9 @@ dependencies = [
 
 [[package]]
 name = "aws-types"
-version = "1.5.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eec1cd5469f328c782dc3e33d4153cf118a54e33cbb3356d60d16f89883e1f94"
+checksum = "e957a6c6dbce82b7a91f44231c09273159703769f447cbe85e854dfe9cf67f86"
 dependencies = [
  "aws-credential-types",
  "aws-smithy-async",
@@ -1795,7 +1904,7 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef"
 dependencies = [
- "fastrand",
+ "fastrand 2.5.0",
  "gloo-timers 0.3.0",
  "tokio",
 ]
@@ -2100,7 +2209,7 @@ dependencies = [
  "cc",
  "cfg-if",
  "constant_time_eq",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
 ]
 
 [[package]]
@@ -2123,11 +2232,11 @@ dependencies = [
 
 [[package]]
 name = "block-padding"
-version = "0.4.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b"
+checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
 dependencies = [
- "hybrid-array",
+ "generic-array",
 ]
 
 [[package]]
@@ -2141,14 +2250,14 @@ dependencies = [
 
 [[package]]
 name = "blocking"
-version = "1.7.0"
+version = "1.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa"
+checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
 dependencies = [
  "async-channel",
  "async-task",
  "futures-io",
- "futures-lite",
+ "futures-lite 2.6.1",
  "piper",
 ]
 
@@ -2190,7 +2299,7 @@ dependencies = [
  "pin-project-lite",
  "rand 0.9.5",
  "rustls",
- "rustls-native-certs",
+ "rustls-native-certs 0.8.4",
  "rustls-pki-types",
  "serde",
  "serde_derive",
@@ -2238,32 +2347,32 @@ dependencies = [
 
 [[package]]
 name = "bon"
-version = "3.10.0"
+version = "3.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e3fac94a66da67200398458a25412bcc3f9b6443b5119a6cad9cf3ccfcd8cc6"
+checksum = "60eafe0d77c3a2fc292c1d1346c3041b33c0a108085a2afabf672b70f69dbbc9"
 dependencies = [
  "bon-macros",
 ]
 
 [[package]]
 name = "bon-macros"
-version = "3.10.0"
+version = "3.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4654961ad0494e4774c5c60b4cb4cd0ae9b9d92d039d901638b1dba97ebebf5"
+checksum = "bd0f9631d8aaaee112c41985d675ef269e02acbd4f33122836af4f0c5f699ff6"
 dependencies = [
  "darling 0.24.1",
  "ident_case",
  "prettyplease 0.3.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
 name = "borsh"
-version = "1.8.1"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a"
+checksum = "a88b7ea17d208c4193f2c1e6de3c35fe71f98c96982d5ced308bdcc749ff6e1f"
 dependencies = [
  "borsh-derive",
  "bytes",
@@ -2272,15 +2381,15 @@ dependencies = [
 
 [[package]]
 name = "borsh-derive"
-version = "1.8.1"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56"
+checksum = "d8f347189c62a579b8cd5f80714efa178f52e461dc2e6d701d264f5ff22e566c"
 dependencies = [
  "once_cell",
  "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -2325,7 +2434,7 @@ dependencies = [
  "getrandom 0.2.17",
  "getrandom 0.3.4",
  "hex",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "js-sys",
  "once_cell",
  "rand 0.9.5",
@@ -2338,9 +2447,9 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "1.13.1"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
+checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530"
 dependencies = [
  "memchr",
  "regex-automata",
@@ -2371,7 +2480,7 @@ dependencies = [
  "chrono",
  "crc",
  "futures",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "itertools 0.14.0",
  "object_store",
  "parquet",
@@ -2410,7 +2519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4a813de7f2bbedb7dce265b64f1cf5908ebe4d56281ece8d847e98113788b9b0"
 dependencies = [
  "rust_decimal",
- "schemars 1.2.2",
+ "schemars 1.2.1",
  "serde",
  "utf8-width",
 ]
@@ -2454,13 +2563,13 @@ dependencies = [
 
 [[package]]
 name = "bytemuck_derive"
-version = "1.12.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f"
+checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -2511,9 +2620,9 @@ dependencies = [
 
 [[package]]
 name = "camino"
-version = "1.2.5"
+version = "1.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0"
 dependencies = [
  "serde_core",
 ]
@@ -2573,18 +2682,18 @@ dependencies = [
 
 [[package]]
 name = "cbc"
-version = "0.2.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896"
+checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
 dependencies = [
- "cipher 0.5.2",
+ "cipher 0.4.4",
 ]
 
 [[package]]
 name = "cc"
-version = "1.4.4"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
+checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8"
 dependencies = [
  "find-msvc-tools",
  "jobserver",
@@ -2615,12 +2724,12 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
 
 [[package]]
 name = "chacha20"
-version = "0.10.2"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
+checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
 dependencies = [
  "cfg-if",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
  "rand_core 0.10.1",
 ]
 
@@ -2686,7 +2795,7 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
 dependencies = [
- "crypto-common 0.1.6",
+ "crypto-common 0.1.7",
  "inout 0.1.4",
 ]
 
@@ -2703,9 +2812,9 @@ dependencies = [
 
 [[package]]
 name = "clang-sys"
-version = "1.9.1"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
 dependencies = [
  "glob",
  "libc",
@@ -2753,7 +2862,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -2784,6 +2893,18 @@ version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
 
+[[package]]
+name = "cms"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730"
+dependencies = [
+ "const-oid 0.9.6",
+ "der",
+ "spki",
+ "x509-cert",
+]
+
 [[package]]
 name = "cobs"
 version = "0.3.0"
@@ -2816,9 +2937,9 @@ dependencies = [
 
 [[package]]
 name = "combine"
-version = "4.6.8"
+version = "4.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
 dependencies = [
  "bytes",
  "memchr",
@@ -2889,7 +3010,7 @@ dependencies = [
  "compio-log",
  "compio-send-wrapper",
  "crossbeam-queue",
- "flume",
+ "flume 0.12.0",
  "futures-util",
  "io-uring",
  "libc",
@@ -2897,10 +3018,10 @@ dependencies = [
  "mod_use",
  "once_cell",
  "pastey 0.2.3",
- "polling",
+ "polling 3.11.0",
  "rustix 1.1.4",
  "smallvec",
- "socket2",
+ "socket2 0.6.5",
  "synchrony",
  "thin-cell",
  "windows-sys 0.61.2",
@@ -2974,7 +3095,7 @@ dependencies = [
  "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -2992,7 +3113,7 @@ dependencies = [
  "libc",
  "once_cell",
  "pin-project-lite",
- "socket2",
+ "socket2 0.6.5",
  "synchrony",
  "widestring",
  "windows-sys 0.61.2",
@@ -3010,7 +3131,7 @@ dependencies = [
  "compio-log",
  "compio-net",
  "compio-runtime",
- "flume",
+ "flume 0.12.0",
  "futures-util",
  "libc",
  "quinn-proto",
@@ -3139,7 +3260,7 @@ dependencies = [
  "darling 0.24.1",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -3277,6 +3398,12 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "cookie-factory"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2"
+
 [[package]]
 name = "core-foundation"
 version = "0.9.4"
@@ -3338,9 +3465,9 @@ dependencies = [
 
 [[package]]
 name = "cpufeatures"
-version = "0.3.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
 dependencies = [
  "libc",
 ]
@@ -3371,9 +3498,9 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.5.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
 dependencies = [
  "cfg-if",
 ]
@@ -3473,9 +3600,9 @@ dependencies = [
 
 [[package]]
 name = "crypto-common"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
 dependencies = [
  "generic-array",
  "rand_core 0.6.4",
@@ -3707,7 +3834,7 @@ dependencies = [
  "hyper",
  "hyper-util",
  "send_wrapper",
- "socket2",
+ "socket2 0.6.5",
  "tokio",
  "tower",
  "tower-service",
@@ -3815,7 +3942,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -3859,7 +3986,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
 dependencies = [
  "darling_core 0.24.1",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -3878,9 +4005,9 @@ dependencies = [
 
 [[package]]
 name = "data-encoding"
-version = "2.11.1"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
+checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
 
 [[package]]
 name = "data-url"
@@ -4030,7 +4157,7 @@ dependencies = [
  "either",
  "futures",
  "humantime",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "itertools 0.14.0",
  "num_cpus",
  "object_store",
@@ -4103,7 +4230,7 @@ dependencies = [
  "deno_path_util",
  "deno_unsync",
  "futures",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "libc",
  "parking_lot",
  "percent-encoding",
@@ -4158,7 +4285,7 @@ version = "0.227.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1bab1eaf578a8cc0ae6fb933e91dc3388b41df22e5974d5891c17ba66b3a0bbb"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "proc-macro-rules",
  "proc-macro2",
  "quote",
@@ -4200,6 +4327,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
 dependencies = [
  "const-oid 0.9.6",
+ "der_derive",
+ "flagset",
  "pem-rfc7468",
  "zeroize",
 ]
@@ -4218,6 +4347,17 @@ dependencies = [
  "rusticata-macros",
 ]
 
+[[package]]
+name = "der_derive"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
 [[package]]
 name = "deranged"
 version = "0.5.8"
@@ -4314,6 +4454,15 @@ dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "des"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e"
+dependencies = [
+ "cipher 0.4.4",
+]
+
 [[package]]
 name = "difflib"
 version = "0.4.0"
@@ -4328,7 +4477,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
 dependencies = [
  "block-buffer 0.10.4",
  "const-oid 0.9.6",
- "crypto-common 0.1.6",
+ "crypto-common 0.1.7",
  "subtle",
 ]
 
@@ -4390,13 +4539,13 @@ dependencies = [
 
 [[package]]
 name = "displaydoc"
-version = "0.2.7"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
+checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -4424,7 +4573,7 @@ checksum = "1aacdd87ba97c2f83ff479e881e547f776b0a7c42921be22d4391f32b6284050"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -4436,6 +4585,12 @@ dependencies = [
  "const-random",
 ]
 
+[[package]]
+name = "doc-comment"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9"
+
 [[package]]
 name = "docker_credential"
 version = "1.4.0"
@@ -4541,9 +4696,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.18.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
+checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
 dependencies = [
  "serde",
 ]
@@ -4777,10 +4932,17 @@ dependencies = [
 
 [[package]]
 name = "event-listener"
-version = "5.4.2"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
+[[package]]
+name = "event-listener"
+version = "5.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2"
+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
 dependencies = [
+ "concurrent-queue",
  "parking",
  "pin-project-lite",
 ]
@@ -4791,10 +4953,19 @@ version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
 dependencies = [
- "event-listener",
+ "event-listener 5.4.1",
  "pin-project-lite",
 ]
 
+[[package]]
+name = "executor-trait"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c39dff9342e4e0e16ce96be751eb21a94e94a87bb2f6e63ad1961c2ce109bf"
+dependencies = [
+ "async-trait",
+]
+
 [[package]]
 name = "expect-test"
 version = "1.5.1"
@@ -4852,6 +5023,15 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 name = "fastrand"
 version = "2.5.0"
@@ -4947,9 +5127,15 @@ dependencies = [
 
 [[package]]
 name = "find-msvc-tools"
-version = "0.1.11"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "flagset"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
+checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
 
 [[package]]
 name = "flatbuffers"
@@ -4963,12 +5149,12 @@ dependencies = [
 
 [[package]]
 name = "flate2"
-version = "1.1.10"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
 dependencies = [
  "crc32fast",
- "miniz_oxide 0.9.1",
+ "miniz_oxide 0.8.9",
  "zlib-rs",
 ]
 
@@ -4987,13 +5173,24 @@ dependencies = [
  "num-traits",
 ]
 
+[[package]]
+name = "flume"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "spin",
+]
+
 [[package]]
 name = "flume"
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be"
 dependencies = [
- "fastrand",
+ "fastrand 2.5.0",
  "futures-core",
  "futures-sink",
  "spin",
@@ -5162,13 +5359,28 @@ version = "0.3.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
 
+[[package]]
+name = "futures-lite"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
+dependencies = [
+ "fastrand 1.9.0",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
 [[package]]
 name = "futures-lite"
 version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
 dependencies = [
- "fastrand",
+ "fastrand 2.5.0",
  "futures-core",
  "futures-io",
  "parking",
@@ -5183,7 +5395,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -5249,9 +5461,9 @@ dependencies = [
 
 [[package]]
 name = "generic-array"
-version = "0.14.9"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -5369,15 +5581,15 @@ dependencies = [
 
 [[package]]
 name = "glob"
-version = "0.3.4"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
 
 [[package]]
 name = "globset"
-version = "0.4.20"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988"
+checksum = "e47d37d2ae4464254884b60ab7071be2b876a9c35b696bd018ddcc76847309cd"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -5817,7 +6029,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http 0.2.12",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "slab",
  "tokio",
  "tokio-util",
@@ -5826,9 +6038,9 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.4.19"
+version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
+checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
 dependencies = [
  "atomic-waker",
  "bytes",
@@ -5836,7 +6048,7 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "http 1.5.0",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "slab",
  "tokio",
  "tokio-util",
@@ -5867,9 +6079,9 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "6.4.4"
+version = "6.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c54236f9045c8004a77942bebc52145b4844639db934a5c70fe08617fbe61a"
+checksum = "4633d16a2350341713c379d6d06a4b9e1845329386026a49ce4fd09c2f3b16f6"
 dependencies = [
  "derive_builder",
  "log",
@@ -5887,7 +6099,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -5974,9 +6186,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hermit-abi"
-version = "0.5.3"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hermit-abi"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284"
+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
 
 [[package]]
 name = "hex"
@@ -6154,9 +6372,9 @@ dependencies = [
 
 [[package]]
 name = "http-body-util"
-version = "0.1.5"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c"
+checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2"
 dependencies = [
  "bytes",
  "futures-core",
@@ -6241,9 +6459,9 @@ dependencies = [
 
 [[package]]
 name = "hybrid-array"
-version = "0.4.14"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
+checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c"
 dependencies = [
  "typenum",
 ]
@@ -6258,7 +6476,7 @@ dependencies = [
  "bytes",
  "futures-channel",
  "futures-core",
- "h2 0.4.19",
+ "h2 0.4.15",
  "http 1.5.0",
  "http-body 1.1.0",
  "httparse",
@@ -6295,7 +6513,7 @@ dependencies = [
  "hyper-util",
  "log",
  "rustls",
- "rustls-native-certs",
+ "rustls-native-certs 0.8.4",
  "tokio",
  "tokio-rustls",
  "tower-service",
@@ -6332,7 +6550,7 @@ dependencies = [
  "libc",
  "percent-encoding",
  "pin-project-lite",
- "socket2",
+ "socket2 0.6.5",
  "system-configuration",
  "tokio",
  "tower-service",
@@ -6478,9 +6696,9 @@ dependencies = [
 
 [[package]]
 name = "icu_collections"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513"
+checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
 dependencies = [
  "displaydoc",
  "potential_utf",
@@ -6492,9 +6710,9 @@ dependencies = [
 
 [[package]]
 name = "icu_locale_core"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb"
+checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
 dependencies = [
  "displaydoc",
  "litemap",
@@ -6505,9 +6723,9 @@ dependencies = [
 
 [[package]]
 name = "icu_normalizer"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f"
+checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
 dependencies = [
  "icu_collections",
  "icu_normalizer_data",
@@ -6519,17 +6737,16 @@ dependencies = [
 
 [[package]]
 name = "icu_normalizer_data"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0"
+checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
 
 [[package]]
 name = "icu_properties"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148"
+checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
 dependencies = [
- "displaydoc",
  "icu_collections",
  "icu_locale_core",
  "icu_properties_data",
@@ -6540,15 +6757,15 @@ dependencies = [
 
 [[package]]
 name = "icu_properties_data"
-version = "2.3.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa"
+checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
 
 [[package]]
 name = "icu_provider"
-version = "2.3.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73"
+checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
 dependencies = [
  "displaydoc",
  "icu_locale_core",
@@ -6603,7 +6820,7 @@ dependencies = [
  "bytemuck",
  "bytes",
  "dashmap",
- "flume",
+ "flume 0.12.0",
  "futures",
  "futures-util",
  "iggy_binary_protocol",
@@ -6709,7 +6926,7 @@ dependencies = [
  "tempfile",
  "thiserror 2.0.20",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
  "tracing-appender",
  "tracing-subscriber",
@@ -6735,7 +6952,7 @@ dependencies = [
  "dotenvy",
  "figlet-rs",
  "figment",
- "flume",
+ "flume 0.12.0",
  "futures",
  "iggy",
  "iggy_common",
@@ -6764,7 +6981,7 @@ dependencies = [
  "tempfile",
  "thiserror 2.0.20",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tower-http 0.7.1",
  "tracing",
  "tracing-opentelemetry",
@@ -6780,7 +6997,7 @@ dependencies = [
  "bytes",
  "kafka-protocol",
  "libc",
- "socket2",
+ "socket2 0.6.5",
  "thiserror 2.0.20",
  "tokio",
  "tokio-util",
@@ -6811,7 +7028,7 @@ dependencies = [
  "sd-notify",
  "serde",
  "serde_json",
- "socket2",
+ "socket2 0.6.5",
  "strum 0.28.0",
  "tempfile",
  "thiserror 2.0.20",
@@ -6885,7 +7102,7 @@ dependencies = [
  "serde_json",
  "simd-json",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
 ]
 
@@ -6980,7 +7197,7 @@ dependencies = [
  "simd-json",
  "strum_macros 0.28.0",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
 ]
 
@@ -7022,7 +7239,7 @@ dependencies = [
  "serde_json",
  "simd-json",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
 ]
 
@@ -7047,7 +7264,7 @@ dependencies = [
  "serde_json",
  "simd-json",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
  "uuid",
 ]
@@ -7141,6 +7358,23 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "iggy_connector_rabbitmq_sink"
+version = "0.4.1-edge.1"
+dependencies = [
+ "async-trait",
+ "dashmap",
+ "iggy",
+ "iggy_common",
+ "iggy_connector_sdk",
+ "lapin",
+ "secrecy",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tracing",
+]
+
 [[package]]
 name = "iggy_connector_random_source"
 version = "0.5.0-edge.4"
@@ -7290,9 +7524,9 @@ dependencies = [
 
 [[package]]
 name = "ignore"
-version = "0.4.33"
+version = "0.4.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f"
+checksum = "7f8a7b8211e695a1d0cd91cace480d4d0bd57667ab10277cc412c5f7f4884f83"
 dependencies = [
  "crossbeam-deque",
  "globset",
@@ -7324,7 +7558,7 @@ dependencies = [
  "rayon",
  "rgb",
  "tiff",
- "zune-core 0.5.3",
+ "zune-core 0.5.1",
  "zune-jpeg 0.5.15",
 ]
 
@@ -7346,15 +7580,15 @@ checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285"
 
 [[package]]
 name = "imgref"
-version = "1.12.3"
+version = "1.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f"
+checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7"
 
 [[package]]
 name = "impl-more"
-version = "0.3.5"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "277ff51754a3f68f12f58446c5d006aa8baa4914ea273cce24a599cfaff33d4f"
+checksum = "35a84fd5aa25fae5c0f4a33d9cac2ca017fc622cbd089be2229993514990f870"
 
 [[package]]
 name = "implicit-clone"
@@ -7363,7 +7597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1689b939ee35e3a075b0834b5672efd43aec8a6e81a1c6002b76a5ca2f211ae0"
 dependencies = [
  "implicit-clone-derive",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
 ]
 
 [[package]]
@@ -7389,9 +7623,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.14.1"
+version = "2.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb"
+checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
 dependencies = [
  "equivalent",
  "hashbrown 0.17.1",
@@ -7413,9 +7647,9 @@ checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
 
 [[package]]
 name = "inotify"
-version = "0.11.5"
+version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592"
+checksum = "153be1941a183ec9ccd095ddbe17a8b8d435ef6c76e9e02451b933c3999af2c8"
 dependencies = [
  "bitflags 2.13.1",
  "inotify-sys",
@@ -7437,6 +7671,7 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
 dependencies = [
+ "block-padding",
  "generic-array",
 ]
 
@@ -7446,10 +7681,18 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
 dependencies = [
- "block-padding",
  "hybrid-array",
 ]
 
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 name = "integer-encoding"
 version = "3.0.4"
@@ -7489,6 +7732,7 @@ dependencies = [
  "journal",
  "jsonwebtoken 11.0.0",
  "keyring-core",
+ "lapin",
  "lazy_static",
  "libc",
  "mongodb",
@@ -7515,7 +7759,7 @@ dependencies = [
  "testcontainers-modules",
  "tokio",
  "tokio-postgres",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tracing",
  "tracing-subscriber",
  "twox-hash",
@@ -7546,11 +7790,22 @@ dependencies = [
  "rustversion",
 ]
 
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.9",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "io-uring"
-version = "0.7.14"
+version = "0.7.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d64d8ca234d152948ceaede1f419b6a83983a5ecccaac05fb337a809c96d3aa6"
+checksum = "9080b15e63775b9a2ac7dca720f7050a8b955e092ea0f6020a4a80f69998cdc0"
 dependencies = [
  "bitflags 2.13.1",
  "cfg-if",
@@ -7563,7 +7818,7 @@ version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222"
 dependencies = [
- "socket2",
+ "socket2 0.6.5",
  "widestring",
  "windows-registry",
  "windows-result 0.4.1",
@@ -7572,9 +7827,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.12.1"
+version = "2.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78"
+checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0"
 dependencies = [
  "serde",
 ]
@@ -7620,9 +7875,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
 
 [[package]]
 name = "jiff"
-version = "0.2.35"
+version = "0.2.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc"
+checksum = "e184d09547b80eb7e20d141ba2fb1fbac843ca53f4cf1b31210adc4c1adc6e16"
 dependencies = [
  "defmt",
  "jiff-core",
@@ -7648,9 +7903,9 @@ dependencies = [
 
 [[package]]
 name = "jiff-static"
-version = "0.2.35"
+version = "0.2.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204"
+checksum = "323da076b7a6faf914dc677cb05a4b907742ff7375c8322c9e7f5061e5e0e9de"
 dependencies = [
  "jiff-core",
  "proc-macro2",
@@ -7748,9 +8003,9 @@ dependencies = [
 
 [[package]]
 name = "js-sys"
-version = "0.3.104"
+version = "0.3.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
+checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
 dependencies = [
  "cfg-if",
  "futures-util",
@@ -7771,7 +8026,7 @@ dependencies = [
  "p256",
  "p384",
  "pem 3.0.6",
- "rand 0.8.8",
+ "rand 0.8.7",
  "rsa",
  "serde",
  "serde_json",
@@ -7795,7 +8050,7 @@ dependencies = [
  "p256",
  "p384",
  "pem 3.0.6",
- "rand 0.8.8",
+ "rand 0.8.7",
  "rsa",
  "serde",
  "serde_json",
@@ -7824,7 +8079,7 @@ dependencies = [
  "clap",
  "hex",
  "iggy-gateway-kafka",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "kafka-protocol",
  "tokio",
  "tracing",
@@ -7841,18 +8096,18 @@ dependencies = [
  "bytes",
  "crc",
  "crc32c",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "uuid",
 ]
 
 [[package]]
 name = "keccak"
-version = "0.2.2"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598"
+checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa"
 dependencies = [
  "cfg-if",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
 ]
 
 [[package]]
@@ -7866,9 +8121,9 @@ dependencies = [
 
 [[package]]
 name = "kqueue"
-version = "1.2.1"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d763e5b24120b4ddf50de6c92308156765aabfbbccebf401da7cff2d70a41ea"
+checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5"
 dependencies = [
  "kqueue-sys",
  "libc",
@@ -7901,6 +8156,28 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
 
+[[package]]
+name = "lapin"
+version = "2.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02d2aa4725b9607915fa1a73e940710a3be6af508ce700e56897cbe8847fbb07"
+dependencies = [
+ "amq-protocol",
+ "async-global-executor-trait",
+ "async-reactor-trait",
+ "async-trait",
+ "executor-trait",
+ "flume 0.11.1",
+ "futures-core",
+ "futures-io",
+ "parking_lot",
+ "pinky-swear",
+ "reactor-trait",
+ "serde",
+ "tracing",
+ "waker-fn",
+]
+
 [[package]]
 name = "lazy-regex"
 version = "3.6.1"
@@ -8031,9 +8308,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.18.8+1.9.7"
+version = "0.18.5+1.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7c568b25d7489bc3fb2988ed69ab111d2944d2f5fec3d5c987fe545ea97b50"
+checksum = "005d6ae6eac1912906073e069f7db60b1fa98e052a68227824afe3e3a1c59ca2"
 dependencies = [
  "cc",
  "libc",
@@ -8053,18 +8330,18 @@ dependencies = [
 
 [[package]]
 name = "liblzma"
-version = "0.4.8"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fe0a34ca854fd4f20c07f696fc8675aec78f87d88d29f5e10257a7490a1b2e1"
+checksum = "45aec2360b3933207e27908049d8e4df4e476b58180afb1e56b2a4fb72efe4ba"
 dependencies = [
  "liblzma-sys",
 ]
 
 [[package]]
 name = "liblzma-sys"
-version = "0.4.8"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0dad045e4b1b7b170be4b60b54b780cafb4490165461bac7d1cf7b703f61d5f"
+checksum = "a046c7f353ba30f810545151e04f63545833803f5b86ee3ddf1517247fe560a5"
 dependencies = [
  "cc",
  "libc",
@@ -8088,9 +8365,9 @@ dependencies = [
 
 [[package]]
 name = "libredox"
-version = "0.1.23"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed"
+checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
 dependencies = [
  "libc",
 ]
@@ -8141,6 +8418,12 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e57c38c1e860fd37c604281cdfb1dd2216977fd76a50f85ba2f388ef3219616"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
 [[package]]
 name = "linux-raw-sys"
 version = "0.4.15"
@@ -8155,9 +8438,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
 
 [[package]]
 name = "litemap"
-version = "0.8.3"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
+checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
 
 [[package]]
 name = "local-channel"
@@ -8172,9 +8455,9 @@ dependencies = [
 
 [[package]]
 name = "local-event"
-version = "0.1.3"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23ab4b951e96ffb2da6e25cec3d038d0e2930f4c406d1ec194b5120ae41ec6d3"
+checksum = "76dda8459b10a8960dfae91c1c77316fc15e7caf94f9f18794126512a8dc77e5"
 
 [[package]]
 name = "local-waker"
@@ -8193,9 +8476,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.34"
+version = "0.4.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
+checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
 
 [[package]]
 name = "logos"
@@ -8524,7 +8807,7 @@ dependencies = [
  "rustls-pemfile",
  "scopeguard",
  "server_common",
- "socket2",
+ "socket2 0.6.5",
  "tempfile",
  "thiserror 2.0.20",
  "tracing",
@@ -8634,7 +8917,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c"
 dependencies = [
  "adler2",
- "simd-adler32",
 ]
 
 [[package]]
@@ -8683,16 +8965,16 @@ checksum = "21909324aa58f5c284d91cac514c6d081210901dc372d7c8ea6a9d7e0406097a"
 
 [[package]]
 name = "moka"
-version = "0.12.16"
+version = "0.12.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4293f18e7567a1caf3c584855554377025c65e0aa445344d04171f5ad63d19b9"
+checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046"
 dependencies = [
- "async-lock",
+ "async-lock 3.4.2",
  "crossbeam-channel",
  "crossbeam-epoch",
  "crossbeam-utils",
  "equivalent",
- "event-listener",
+ "event-listener 5.4.1",
  "futures-util",
  "parking_lot",
  "portable-atomic",
@@ -8721,9 +9003,9 @@ checksum = "851fac73f7fe22f6a3ab87f720ce509cae7c9fd08e7dd27866cc232dee07ccf4"
 
 [[package]]
 name = "mongodb"
-version = "3.8.2"
+version = "3.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d220eb9ba80bad420e1f9efc4e895fede7418f8779a8e38a3b750e57ff397720"
+checksum = "fd64784a1fdbcf2a334717446edc583061159067a2e7cc326ee567ecf035f07b"
 dependencies = [
  "base64 0.22.1",
  "bitflags 2.13.1",
@@ -8742,7 +9024,7 @@ dependencies = [
  "md-5 0.11.0",
  "mongocrypt",
  "mongodb-internal-macros",
- "pbkdf2",
+ "pbkdf2 0.13.0",
  "percent-encoding",
  "rand 0.9.5",
  "rustc_version_runtime",
@@ -8752,7 +9034,7 @@ dependencies = [
  "serde_with",
  "sha1 0.11.0",
  "sha2 0.11.0",
- "socket2",
+ "socket2 0.6.5",
  "stringprep",
  "strsim",
  "take_mut",
@@ -8767,9 +9049,9 @@ dependencies = [
 
 [[package]]
 name = "mongodb-internal-macros"
-version = "3.8.2"
+version = "3.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e38ff3c46c59c2f4d9b26a86e6980dc23583e9d4b45aa579cef6584642093128"
+checksum = "f243f9039382cd06378f13980b79700236468b6fb22f24abfa99783e9569f1a3"
 dependencies = [
  "macro_magic",
  "proc-macro2",
@@ -8947,7 +9229,7 @@ checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
 dependencies = [
  "num-integer",
  "num-traits",
- "rand 0.8.8",
+ "rand 0.8.7",
  "serde",
 ]
 
@@ -8962,7 +9244,7 @@ dependencies = [
  "num-integer",
  "num-iter",
  "num-traits",
- "rand 0.8.8",
+ "rand 0.8.7",
  "smallvec",
  "zeroize",
 ]
@@ -8996,9 +9278,9 @@ dependencies = [
 
 [[package]]
 name = "num-integer"
-version = "0.1.47"
+version = "0.1.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
 dependencies = [
  "num-traits",
 ]
@@ -9015,9 +9297,9 @@ dependencies = [
 
 [[package]]
 name = "num-modular"
-version = "0.6.5"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd8e500409e6cd603b03e477c26a6caecdc27ac58979a53e881c75eafc079f44"
+checksum = "fc41a1374056e9672221567958a66c16be12d0e2c1b408761e14d901c237d5e0"
 
 [[package]]
 name = "num-order"
@@ -9055,7 +9337,7 @@ version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.5.2",
  "libc",
 ]
 
@@ -9136,9 +9418,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.39.1"
+version = "0.37.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b"
+checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
 dependencies = [
  "memchr",
 ]
@@ -9378,6 +9660,12 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
 [[package]]
 name = "openssl-probe"
 version = "0.2.1"
@@ -9560,6 +9848,28 @@ version = "4.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8"
 
+[[package]]
+name = "p12-keystore"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cae83056e7cb770211494a0ecf66d9fa7eba7d00977e5bb91f0e925b40b937f"
+dependencies = [
+ "cbc",
+ "cms",
+ "der",
+ "des",
+ "hex",
+ "hmac 0.12.1",
+ "pkcs12",
+ "pkcs5",
+ "rand 0.9.5",
+ "rc2",
+ "sha1 0.10.7",
+ "sha2 0.10.9",
+ "thiserror 2.0.20",
+ "x509-parser 0.17.0",
+]
+
 [[package]]
 name = "p256"
 version = "0.13.2"
@@ -9747,6 +10057,16 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
 
+[[package]]
+name = "pbkdf2"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
+dependencies = [
+ "digest 0.10.7",
+ "hmac 0.12.1",
+]
+
 [[package]]
 name = "pbkdf2"
 version = "0.13.0"
@@ -9849,9 +10169,9 @@ checksum = "3637c05577168127568a64e9dc5a6887da720efef07b3d9472d45f63ab191166"
 
 [[package]]
 name = "pest"
-version = "2.9.0"
+version = "2.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a07a60cc7a4d00c91f95c685609d1d2f79050e6804b70ebedd7650f0b839bcf"
+checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9"
 dependencies = [
  "memchr",
  "ucd-trie",
@@ -9859,9 +10179,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.9.0"
+version = "2.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3a83744a5c8455b8b3e0dc5031362780a347c878bdd11584d1a8984228cc88d"
+checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58"
 dependencies = [
  "pest",
  "pest_generator",
@@ -9869,9 +10189,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.9.0"
+version = "2.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0cd3451aa3de60d4b9a1e736885e4dea6b31617598026f12256ad566d63304a"
+checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7"
 dependencies = [
  "pest",
  "pest_meta",
@@ -9882,9 +10202,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.9.0"
+version = "2.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e04d3a0849e241d7dfce834c83b1c5edc8622009e8dd51a12ba1927c32f05496"
+checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210"
 dependencies = [
  "pest",
 ]
@@ -10019,6 +10339,18 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
+[[package]]
+name = "pinky-swear"
+version = "6.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1ea6e230dd3a64d61bcb8b79e597d3ab6b4c94ec7a234ce687dd718b4f2e657"
+dependencies = [
+ "doc-comment",
+ "flume 0.11.1",
+ "parking_lot",
+ "tracing",
+]
+
 [[package]]
 name = "pinned"
 version = "0.1.0"
@@ -10037,7 +10369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
 dependencies = [
  "atomic-waker",
- "fastrand",
+ "fastrand 2.5.0",
  "futures-io",
 ]
 
@@ -10052,6 +10384,36 @@ dependencies = [
  "spki",
 ]
 
+[[package]]
+name = "pkcs12"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "695b3df3d3cc1015f12d70235e35b6b79befc5fa7a9b95b951eab1dd07c9efc2"
+dependencies = [
+ "cms",
+ "const-oid 0.9.6",
+ "der",
+ "digest 0.10.7",
+ "spki",
+ "x509-cert",
+ "zeroize",
+]
+
+[[package]]
+name = "pkcs5"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6"
+dependencies = [
+ "aes 0.8.4",
+ "cbc",
+ "der",
+ "pbkdf2 0.12.2",
+ "scrypt",
+ "sha2 0.10.9",
+ "spki",
+]
+
 [[package]]
 name = "pkcs8"
 version = "0.10.2"
@@ -10064,9 +10426,9 @@ dependencies = [
 
 [[package]]
 name = "pkg-config"
-version = "0.3.34"
+version = "0.3.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
+checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
 
 [[package]]
 name = "png"
@@ -10100,6 +10462,22 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5dcdc93847ad24990939cce6e1804361e903efcb5f99daa5abd87943a9d6d7ba"
 
+[[package]]
+name = "polling"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
+dependencies = [
+ "autocfg",
+ "bitflags 1.3.2",
+ "cfg-if",
+ "concurrent-queue",
+ "libc",
+ "log",
+ "pin-project-lite",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "polling"
 version = "3.11.0"
@@ -10108,7 +10486,7 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
 dependencies = [
  "cfg-if",
  "concurrent-queue",
- "hermit-abi",
+ "hermit-abi 0.5.2",
  "pin-project-lite",
  "rustix 1.1.4",
  "windows-sys 0.61.2",
@@ -10133,15 +10511,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd"
 dependencies = [
  "cpubits",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
  "universal-hash 0.6.1",
 ]
 
 [[package]]
 name = "portable-atomic"
-version = "1.15.0"
+version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
+checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3"
 
 [[package]]
 name = "portable-atomic-util"
@@ -10200,9 +10578,9 @@ dependencies = [
 
 [[package]]
 name = "potential_utf"
-version = "0.1.6"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661"
+checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
 dependencies = [
  "zerovec",
 ]
@@ -10280,7 +10658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2bfe0f4c752e450fc2faf62654f1c134747922825d5b04ca717b8874f41a40c0"
 dependencies = [
  "proc-macro2",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -10441,7 +10819,7 @@ checksum = "01e34894696ff94f64a20c2c373a6440903e9c2789a303d68ec6e6f953f890e4"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -10517,9 +10895,9 @@ dependencies = [
 
 [[package]]
 name = "psm"
-version = "0.1.32"
+version = "0.1.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd034599e63b970727f70d79e02d62390a4a84f7c6b827c27c46d5ac3fa622"
+checksum = "645dbe486e346d9b5de3ef16ede18c26e6c70ad97418f4874b8b1889d6e761ea"
 dependencies = [
  "ar_archive_writer",
  "cc",
@@ -10653,7 +11031,7 @@ dependencies = [
  "quinn-udp",
  "rustc-hash",
  "rustls",
- "socket2",
+ "socket2 0.6.5",
  "thiserror 2.0.20",
  "tokio",
  "tracing",
@@ -10662,9 +11040,9 @@ dependencies = [
 
 [[package]]
 name = "quinn-proto"
-version = "0.11.17"
+version = "0.11.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83"
+checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
 dependencies = [
  "aws-lc-rs",
  "bytes",
@@ -10694,7 +11072,7 @@ dependencies = [
  "cfg_aliases",
  "libc",
  "once_cell",
- "socket2",
+ "socket2 0.6.5",
  "tracing",
  "windows-sys 0.61.2",
 ]
@@ -10728,9 +11106,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
 
 [[package]]
 name = "rand"
-version = "0.8.8"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
+checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
 dependencies = [
  "libc",
  "rand_chacha 0.3.1",
@@ -10899,6 +11277,15 @@ dependencies = [
  "crossbeam-utils",
 ]
 
+[[package]]
+name = "rc2"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd"
+dependencies = [
+ "cipher 0.4.4",
+]
+
 [[package]]
 name = "rcgen"
 version = "0.14.10"
@@ -10909,10 +11296,21 @@ dependencies = [
  "ring",
  "rustls-pki-types",
  "time",
- "x509-parser",
+ "x509-parser 0.18.1",
  "yasna",
 ]
 
+[[package]]
+name = "reactor-trait"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "438a4293e4d097556730f4711998189416232f009c137389e0f961d2bc0ddc58"
+dependencies = [
+ "async-trait",
+ "futures-core",
+ "futures-io",
+]
+
 [[package]]
 name = "reborrow"
 version = "0.5.5"
@@ -10961,22 +11359,22 @@ dependencies = [
 
 [[package]]
 name = "ref-cast"
-version = "1.0.27"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3"
+checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d"
 dependencies = [
  "ref-cast-impl",
 ]
 
 [[package]]
 name = "ref-cast-impl"
-version = "1.0.27"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a"
+checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -10993,9 +11391,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.18"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
+checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -11102,7 +11500,7 @@ dependencies = [
  "bytes",
  "futures-core",
  "futures-util",
- "h2 0.4.19",
+ "h2 0.4.15",
  "http 1.5.0",
  "http-body 1.1.0",
  "http-body-util",
@@ -11115,7 +11513,7 @@ dependencies = [
  "pin-project-lite",
  "quinn",
  "rustls",
- "rustls-native-certs",
+ "rustls-native-certs 0.8.4",
  "rustls-pki-types",
  "serde",
  "serde_json",
@@ -11147,7 +11545,7 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2 0.4.19",
+ "h2 0.4.15",
  "http 1.5.0",
  "http-body 1.1.0",
  "http-body-util",
@@ -11346,13 +11744,13 @@ dependencies = [
  "http 1.5.0",
  "http-body 1.1.0",
  "http-body-util",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "pastey 0.2.3",
  "pin-project-lite",
  "rand 0.10.2",
  "reqwest 0.13.4",
  "rmcp-macros",
- "schemars 1.2.2",
+ "schemars 1.2.1",
  "serde",
  "serde_json",
  "sse-stream",
@@ -11375,7 +11773,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde_json",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -11399,9 +11797,9 @@ dependencies = [
 
 [[package]]
 name = "roaring"
-version = "0.11.5"
+version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18bd8a37d17a58532776dcdf6041ce64929adca78e8489d5cacbafe99229d3e1"
+checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9"
 dependencies = [
  "bytemuck",
  "byteorder",
@@ -11539,7 +11937,7 @@ dependencies = [
  "bytes",
  "num-traits",
  "postgres-types",
- "rand 0.8.8",
+ "rand 0.8.7",
  "rkyv",
  "serde",
  "serde_json",
@@ -11580,6 +11978,20 @@ dependencies = [
  "nom 7.1.3",
 ]
 
+[[package]]
+name = "rustix"
+version = "0.37.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys 0.3.8",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "rustix"
 version = "0.38.44"
@@ -11608,9 +12020,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.43"
+version = "0.23.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
+checksum = "6725596c3f2c3a0aef021139e145d4eafe314a6623e4680ca83852b2c67ab2ba"
 dependencies = [
  "aws-lc-rs",
  "log",
@@ -11622,16 +12034,42 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "rustls-connector"
+version = "0.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70cc376c6ba1823ae229bacf8ad93c136d93524eab0e4e5e0e4f96b9c4e5b212"
+dependencies = [
+ "log",
+ "rustls",
+ "rustls-native-certs 0.7.3",
+ "rustls-pki-types",
+ "rustls-webpki",
+]
+
+[[package]]
+name = "rustls-native-certs"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
+dependencies = [
+ "openssl-probe 0.1.6",
+ "rustls-pemfile",
+ "rustls-pki-types",
+ "schannel",
+ "security-framework 2.11.1",
+]
+
 [[package]]
 name = "rustls-native-certs"
 version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
 dependencies = [
- "openssl-probe",
+ "openssl-probe 0.2.1",
  "rustls-pki-types",
  "schannel",
- "security-framework",
+ "security-framework 3.7.0",
 ]
 
 [[package]]
@@ -11645,9 +12083,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.15.1"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
+checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
 dependencies = [
  "web-time",
  "zeroize",
@@ -11665,10 +12103,10 @@ dependencies = [
  "log",
  "once_cell",
  "rustls",
- "rustls-native-certs",
+ "rustls-native-certs 0.8.4",
  "rustls-platform-verifier-android",
  "rustls-webpki",
- "security-framework",
+ "security-framework 3.7.0",
  "security-framework-sys",
  "webpki-root-certs",
  "windows-sys 0.61.2",
@@ -11741,6 +12179,15 @@ version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
 
+[[package]]
+name = "salsa20"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
+dependencies = [
+ "cipher 0.4.4",
+]
+
 [[package]]
 name = "same-file"
 version = "1.0.6"
@@ -11773,9 +12220,9 @@ dependencies = [
 
 [[package]]
 name = "schemars"
-version = "1.2.2"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a"
+checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
 dependencies = [
  "chrono",
  "dyn-clone",
@@ -11787,14 +12234,14 @@ dependencies = [
 
 [[package]]
 name = "schemars_derive"
-version = "1.2.2"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba"
+checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f"
 dependencies = [
  "proc-macro2",
  "quote",
  "serde_derive_internals",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -11809,6 +12256,17 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
+[[package]]
+name = "scrypt"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
+dependencies = [
+ "pbkdf2 0.12.2",
+ "salsa20",
+ "sha2 0.10.9",
+]
+
 [[package]]
 name = "sd-notify"
 version = "0.5.0"
@@ -11861,23 +12319,36 @@ dependencies = [
 
 [[package]]
 name = "secret-service"
-version = "5.2.0"
+version = "5.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5107b24b91445dd2aa449a258a1807b63240942157292354dc5bfdbeb8bc6db8"
+checksum = "9a62d7f86047af0077255a29494136b9aaaf697c76ff70b8e49cded4e2623c14"
 dependencies = [
- "aes 0.9.3",
+ "aes 0.8.4",
  "cbc",
  "futures-util",
- "getrandom 0.4.3",
- "hkdf 0.13.0",
- "hybrid-array",
+ "generic-array",
+ "getrandom 0.2.17",
+ "hkdf 0.12.4",
  "num",
  "once_cell",
  "serde",
- "sha2 0.11.0",
+ "sha2 0.10.9",
  "zbus",
 ]
 
+[[package]]
+name = "security-framework"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
+dependencies = [
+ "bitflags 2.13.1",
+ "core-foundation 0.9.4",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
 [[package]]
 name = "security-framework"
 version = "3.7.0"
@@ -11993,18 +12464,18 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
 name = "serde_derive_internals"
-version = "0.30.0"
+version = "0.29.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd"
+checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -12013,7 +12484,7 @@ version = "1.0.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "itoa",
  "memchr",
  "serde",
@@ -12040,7 +12511,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -12098,10 +12569,10 @@ dependencies = [
  "chrono",
  "hex",
  "indexmap 1.9.3",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "jiff",
  "schemars 0.9.0",
- "schemars 1.2.2",
+ "schemars 1.2.1",
  "serde_core",
  "serde_json",
  "serde_with_macros",
@@ -12126,7 +12597,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "itoa",
  "ryu",
  "serde",
@@ -12155,7 +12626,7 @@ checksum = "a22144e767da4ddd8416dbf383700542ffd8a5dc493dfecedfe1fe3ad03c98ae"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -12229,15 +12700,15 @@ dependencies = [
  "serde_json",
  "server_common",
  "shard",
- "socket2",
+ "socket2 0.6.5",
  "strum 0.28.0",
- "syn 3.0.4",
+ "syn 3.0.5",
  "sysinfo 0.39.6",
  "system_stats",
  "tempfile",
  "thiserror 2.0.20",
  "tokio",
- "toml 1.1.4+spec-1.1.0",
+ "toml 1.1.5+spec-1.1.0",
  "tower-http 0.7.1",
  "tracing",
  "tracing-appender",
@@ -12306,7 +12777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
 dependencies = [
  "cfg-if",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
  "digest 0.11.3",
 ]
 
@@ -12328,7 +12799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
 dependencies = [
  "cfg-if",
- "cpufeatures 0.3.1",
+ "cpufeatures 0.3.0",
  "digest 0.11.3",
 ]
 
@@ -12486,7 +12957,7 @@ dependencies = [
  "futures",
  "iggy_binary_protocol",
  "iggy_common",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "journal",
  "message_bus",
  "metadata",
@@ -12587,6 +13058,16 @@ version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886"
 
+[[package]]
+name = "socket2"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "socket2"
 version = "0.6.5"
@@ -12707,14 +13188,14 @@ dependencies = [
  "crc",
  "crossbeam-queue",
  "either",
- "event-listener",
+ "event-listener 5.4.1",
  "futures-core",
  "futures-intrusive",
  "futures-io",
  "futures-util",
  "hashbrown 0.16.1",
  "hashlink",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "log",
  "memchr",
  "percent-encoding",
@@ -12844,7 +13325,7 @@ checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c"
 dependencies = [
  "atoi",
  "chrono",
- "flume",
+ "flume 0.12.0",
  "form_urlencoded",
  "futures-channel",
  "futures-core",
@@ -12864,9 +13345,9 @@ dependencies = [
 
 [[package]]
 name = "sse-stream"
-version = "0.2.5"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c123f296ade4ec4b8b0f6162116e6629f5146922ca5ab40ca9d3c2e73ab4761e"
+checksum = "39f24a9b78c40b90817bbcd1821c74ddfd74916aadd29403d001532a9195532d"
 dependencies = [
  "bytes",
  "futures-util",
@@ -12883,9 +13364,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
 
 [[package]]
 name = "stacker"
-version = "0.1.25"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967"
+checksum = "640c8cdd92b6b12f5bcb1803ca3bbf5ab96e5e6b6b96b9ab77dabe9e880b3190"
 dependencies = [
  "cc",
  "cfg-if",
@@ -13057,9 +13538,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "3.0.4"
+version = "3.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
+checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -13081,7 +13562,7 @@ version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f9d6d5fbc4583cf3e5eee953506f13853a42ee6b4a21a983dffffb10c765cb80"
 dependencies = [
- "event-listener",
+ "event-listener 5.4.1",
  "futures-util",
  "local-event",
  "loom",
@@ -13239,13 +13720,25 @@ dependencies = [
  "xattr",
 ]
 
+[[package]]
+name = "tcp-stream"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "495b0abdce3dc1f8fd27240651c9e68890c14e9d9c61527b1ce44d8a5a7bd3d5"
+dependencies = [
+ "cfg-if",
+ "p12-keystore",
+ "rustls-connector",
+ "rustls-pemfile",
+]
+
 [[package]]
 name = "tempfile"
 version = "3.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
 dependencies = [
- "fastrand",
+ "fastrand 2.5.0",
  "getrandom 0.4.3",
  "once_cell",
  "rustix 1.1.4",
@@ -13399,7 +13892,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -13438,9 +13931,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.55"
+version = "0.3.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
+checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244"
 dependencies = [
  "deranged",
  "libc",
@@ -13505,9 +13998,9 @@ dependencies = [
 
 [[package]]
 name = "tinystr"
-version = "0.8.4"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643"
+checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
 dependencies = [
  "displaydoc",
  "zerovec",
@@ -13540,20 +14033,20 @@ dependencies = [
  "parking_lot",
  "pin-project-lite",
  "signal-hook-registry",
- "socket2",
+ "socket2 0.6.5",
  "tokio-macros",
  "windows-sys 0.61.2",
 ]
 
 [[package]]
 name = "tokio-macros"
-version = "2.7.2"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
+checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -13576,7 +14069,7 @@ dependencies = [
  "postgres-protocol",
  "postgres-types",
  "rand 0.10.2",
- "socket2",
+ "socket2 0.6.5",
  "tokio",
  "tokio-util",
  "whoami",
@@ -13594,9 +14087,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.19"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
+checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -13666,11 +14159,11 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "1.1.4+spec-1.1.0"
+version = "1.1.5+spec-1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5"
+checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "serde_core",
  "serde_spanned 1.1.1",
  "toml_datetime 1.1.1+spec-1.1.0",
@@ -13703,7 +14196,7 @@ version = "0.19.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "toml_datetime 0.6.11",
  "winnow 0.5.40",
 ]
@@ -13714,7 +14207,7 @@ version = "0.22.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
 dependencies = [
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "serde",
  "serde_spanned 0.6.9",
  "toml_datetime 0.6.11",
@@ -13753,7 +14246,7 @@ dependencies = [
  "axum",
  "base64 0.22.1",
  "bytes",
- "h2 0.4.19",
+ "h2 0.4.15",
  "http 1.5.0",
  "http-body 1.1.0",
  "http-body-util",
@@ -13762,7 +14255,7 @@ dependencies = [
  "hyper-util",
  "percent-encoding",
  "pin-project",
- "socket2",
+ "socket2 0.6.5",
  "sync_wrapper",
  "tokio",
  "tokio-stream",
@@ -13815,7 +14308,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
 dependencies = [
  "futures-core",
  "futures-util",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "pin-project-lite",
  "slab",
  "sync_wrapper",
@@ -14153,7 +14646,7 @@ checksum = "f153acc4e99a5f2a5aefa09fb078be54e26271b2813f6041200b224c098d8328"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 3.0.5",
 ]
 
 [[package]]
@@ -14291,7 +14784,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
 dependencies = [
- "crypto-common 0.1.6",
+ "crypto-common 0.1.7",
  "subtle",
 ]
 
@@ -14325,11 +14818,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
 
 [[package]]
 name = "ureq"
-version = "3.4.0"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d"
+checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
 dependencies = [
- "base64 0.23.1",
+ "base64 0.22.1",
  "flate2",
  "log",
  "percent-encoding",
@@ -14342,11 +14835,11 @@ dependencies = [
 
 [[package]]
 name = "ureq-proto"
-version = "0.6.1"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613"
+checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
 dependencies = [
- "base64 0.23.1",
+ "base64 0.22.1",
  "http 1.5.0",
  "httparse",
  "log",
@@ -14600,6 +15093,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "waker-fn"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
+
 [[package]]
 name = "walkdir"
 version = "2.5.0"
@@ -14654,9 +15153,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.127"
+version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
+checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -14668,9 +15167,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.77"
+version = "0.4.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950"
+checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -14678,9 +15177,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.127"
+version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
+checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -14688,9 +15187,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.127"
+version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
+checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
 dependencies = [
  "bumpalo",
  "proc-macro2",
@@ -14701,9 +15200,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.127"
+version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
+checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
 dependencies = [
  "unicode-ident",
 ]
@@ -14760,9 +15259,9 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.104"
+version = "0.3.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30"
+checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -14826,9 +15325,9 @@ dependencies = [
 
 [[package]]
 name = "whoami"
-version = "2.1.3"
+version = "2.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626c4bac6755d76ffc12cb01b2eac751db1996b9e0041de9aa02c8c211ddc82c"
+checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d"
 dependencies = [
  "libc",
  "libredox",
@@ -15079,6 +15578,15 @@ dependencies = [
  "windows-link 0.2.1",
 ]
 
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.52.0"
@@ -15115,6 +15623,21 @@ dependencies = [
  "windows-link 0.2.1",
 ]
 
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
 [[package]]
 name = "windows-targets"
 version = "0.52.6"
@@ -15166,6 +15689,12 @@ dependencies = [
  "windows-link 0.2.1",
 ]
 
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.52.6"
@@ -15178,6 +15707,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
@@ -15190,6 +15725,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
@@ -15214,6 +15755,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
@@ -15226,6 +15773,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.52.6"
@@ -15238,6 +15791,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
 
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.52.6"
@@ -15250,6 +15809,12 @@ version = "0.53.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.52.6"
@@ -15326,9 +15891,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
 
 [[package]]
 name = "writeable"
-version = "0.6.4"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
+checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
 
 [[package]]
 name = "wyz"
@@ -15339,6 +15904,17 @@ dependencies = [
  "tap",
 ]
 
+[[package]]
+name = "x509-cert"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94"
+dependencies = [
+ "const-oid 0.9.6",
+ "der",
+ "spki",
+]
+
 [[package]]
 name = "x509-certificate"
 version = "0.25.0"
@@ -15358,6 +15934,23 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "x509-parser"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460"
+dependencies = [
+ "asn1-rs",
+ "data-encoding",
+ "der-parser",
+ "lazy_static",
+ "nom 7.1.3",
+ "oid-registry",
+ "rusticata-macros",
+ "thiserror 2.0.20",
+ "time",
+]
+
 [[package]]
 name = "x509-parser"
 version = "0.18.1"
@@ -15441,7 +16034,7 @@ dependencies = [
  "futures",
  "gloo 0.11.0",
  "implicit-clone",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "js-sys",
  "rustversion",
  "serde",
@@ -15531,23 +16124,23 @@ checksum = "c6e61e59a957b7ccee15d2049f86e8bfd6f66968fcd88f018950662d9b86e675"
 
 [[package]]
 name = "zbus"
-version = "5.19.0"
+version = "5.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907"
+checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a"
 dependencies = [
  "async-broadcast",
  "async-executor",
- "async-io",
- "async-lock",
+ "async-io 2.6.0",
+ "async-lock 3.4.2",
  "async-process",
  "async-recursion",
  "async-task",
  "async-trait",
  "blocking",
  "enumflags2",
- "event-listener",
+ "event-listener 5.4.1",
  "futures-core",
- "futures-lite",
+ "futures-lite 2.6.1",
  "hex",
  "libc",
  "ordered-stream",
@@ -15577,14 +16170,14 @@ dependencies = [
 
 [[package]]
 name = "zbus_macros"
-version = "5.19.0"
+version = "5.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40"
+checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119"
 dependencies = [
  "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
  "zbus_names",
  "zvariant",
  "zvariant_utils",
@@ -15601,29 +16194,20 @@ dependencies = [
  "zvariant",
 ]
 
-[[package]]
-name = "zcheapstr"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473"
-dependencies = [
- "serde",
-]
-
 [[package]]
 name = "zerocopy"
-version = "0.8.56"
+version = "0.8.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
+checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.8.56"
+version = "0.8.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
+checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -15673,9 +16257,9 @@ dependencies = [
 
 [[package]]
 name = "zerotrie"
-version = "0.2.5"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f"
+checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
 dependencies = [
  "displaydoc",
  "yoke",
@@ -15684,9 +16268,9 @@ dependencies = [
 
 [[package]]
 name = "zerovec"
-version = "0.11.8"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8"
+checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
 dependencies = [
  "yoke",
  "zerofrom",
@@ -15695,13 +16279,13 @@ dependencies = [
 
 [[package]]
 name = "zerovec-derive"
-version = "0.11.6"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da"
+checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
 ]
 
 [[package]]
@@ -15724,7 +16308,7 @@ checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b"
 dependencies = [
  "crc32fast",
  "flate2",
- "indexmap 2.14.1",
+ "indexmap 2.14.2",
  "memchr",
  "typed-path",
  "zopfli",
@@ -15732,9 +16316,9 @@ dependencies = [
 
 [[package]]
 name = "zlib-rs"
-version = "0.6.7"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12"
+checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
 
 [[package]]
 name = "zmij"
@@ -15790,9 +16374,9 @@ checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
 
 [[package]]
 name = "zune-core"
-version = "0.5.3"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b"
+checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
 
 [[package]]
 name = "zune-inflate"
@@ -15818,46 +16402,45 @@ version = "0.5.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
 dependencies = [
- "zune-core 0.5.3",
+ "zune-core 0.5.1",
 ]
 
 [[package]]
 name = "zvariant"
-version = "5.15.0"
+version = "5.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147"
+checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911"
 dependencies = [
  "endi",
  "enumflags2",
  "serde",
  "winnow 1.0.4",
- "zcheapstr",
  "zvariant_derive",
  "zvariant_utils",
 ]
 
 [[package]]
 name = "zvariant_derive"
-version = "5.15.0"
+version = "5.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497"
+checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12"
 dependencies = [
  "proc-macro-crate 3.3.0",
  "proc-macro2",
  "quote",
- "syn 3.0.4",
+ "syn 2.0.119",
  "zvariant_utils",
 ]
 
 [[package]]
 name = "zvariant_utils"
-version = "4.2.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3"
+checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7"
 dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 3.0.4",
+ "syn 2.0.119",
  "winnow 1.0.4",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 43747aae0..b84d88074 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -44,6 +44,7 @@ members = [
     "core/connectors/sinks/mongodb_sink",
     "core/connectors/sinks/postgres_sink",
     "core/connectors/sinks/quickwit_sink",
+    "core/connectors/sinks/rabbitmq_sink",
     "core/connectors/sinks/redshift_sink",
     "core/connectors/sinks/s3_sink",
     "core/connectors/sinks/stdout_sink",
@@ -213,6 +214,7 @@ js-sys = "0.3"
 jsonwebtoken = { version = "11.0.0", features = ["rust_crypto"] }
 kafka-protocol = { version = "0.18.0", default-features = false, features = ["broker"] }
 keyring-core = "1.0.0"
+lapin = "2.5.1"
 lazy_static = "1.5.0"
 # Pinned exactly: `metadata::stm::stream`'s keyed stats evictions lean on
 # left-right draining the previous batch's `absorb_second` before the current
diff --git a/core/connectors/README.md b/core/connectors/README.md
index 890a263b5..f88b3d255 100644
--- a/core/connectors/README.md
+++ b/core/connectors/README.md
@@ -86,6 +86,7 @@ Each sink should have its own, custom configuration, which is passed along with
 - **Meilisearch Sink** - indexes messages in Meilisearch
 - **PostgreSQL Sink** - stores messages in PostgreSQL database tables
 - **Quickwit Sink** - indexes messages in Quickwit search engine
+- **RabbitMQ Sink** - publishes messages to RabbitMQ exchanges via AMQP 0.9.1
 - **Reshift Sink** - stores messages in Redshift warehouse tables via S3 as staging
 - **S3 Sink** - writes messages to Amazon S3 and S3-compatible stores (MinIO, R2, B2, DO Spaces)
 - **Stdout Sink** - prints messages to standard output (useful for debugging/development)
diff --git a/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml b/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml
new file mode 100644
index 000000000..8d09f65ee
--- /dev/null
+++ b/core/connectors/runtime/example_config/connectors/rabbitmq_sink.toml
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+type = "sink"
+key = "rabbitmq"
+enabled = true
+version = 0
+name = "RabbitMQ sink"
+path = "target/release/libiggy_connector_rabbitmq_sink"
+verbose = true
+
+[[streams]]
+stream = "example_stream"
+topics = ["example_topic"]
+schema = "json"
+batch_length = 100
+poll_interval = "5ms"
+consumer_group = "rabbitmq_sink_connector"
+
+[plugin_config]
+amqp_url = "amqp://guest:guest@localhost:5672"
+exchange = "iggy_events"
+exchange_type = "topic"
+routing_key = "iggy.messages"
+durable_exchange = true
+delivery_mode = "persistent"
+include_metadata = true
+verbose_logging = false
+max_retries = 3
+retry_delay_secs = 1
+max_retry_delay_secs = 5
+timeout_secs = 30
diff --git a/core/connectors/sinks/README.md b/core/connectors/sinks/README.md
index 91de1fd08..1046edb4c 100644
--- a/core/connectors/sinks/README.md
+++ b/core/connectors/sinks/README.md
@@ -19,6 +19,7 @@ Sink connectors are responsible for writing data from Iggy streams to external s
 | **s3_sink** | Writes messages to Amazon S3 and S3-compatible stores (MinIO, R2, B2, DO Spaces) |
 | **stdout_sink** | Prints messages to standard output (useful for debugging and development) |
 | **surrealdb_sink** | Writes messages into SurrealDB with deterministic record IDs for idempotent replay |
+| **rabbitmq_sink** | Publishes messages to RabbitMQ exchanges via AMQP |
 
 The sink is represented by the single `Sink` trait, which defines the basic interface for all sink connectors. It provides methods for initializing the sink, writing data to external destination, and closing the sink.
 
diff --git a/core/connectors/sinks/rabbitmq_sink/Cargo.toml b/core/connectors/sinks/rabbitmq_sink/Cargo.toml
new file mode 100644
index 000000000..2fd4dd715
--- /dev/null
+++ b/core/connectors/sinks/rabbitmq_sink/Cargo.toml
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "iggy_connector_rabbitmq_sink"
+version = "0.4.1-edge.1"
+description = "Iggy RabbitMQ sink connector for publishing stream messages to RabbitMQ exchanges via AMQP 0.9.1"
+edition = "2024"
+license = "Apache-2.0"
+keywords = ["iggy", "messaging", "streaming", "rabbitmq", "amqp", "sink"]
+categories = ["command-line-utilities", "database", "network-programming"]
+homepage = "https://iggy.apache.org"
+documentation = "https://iggy.apache.org/docs"
+repository = "https://github.com/apache/iggy"
+readme = "../../README.md"
+publish = false
+
+[package.metadata.cargo-machete]
+ignored = ["dashmap"]
+
+[lib]
+crate-type = ["cdylib", "lib"]
+
+[dependencies]
+async-trait = { workspace = true }
+dashmap = { workspace = true }
+iggy = { workspace = true }
+iggy_common = { workspace = true }
+iggy_connector_sdk = { workspace = true }
+lapin = { workspace = true }
+secrecy = { workspace = true }
+serde = { workspace = true }
+tokio = { workspace = true }
+tracing = { workspace = true }
+
+[dev-dependencies]
+serde_json = { workspace = true }
diff --git a/core/connectors/sinks/rabbitmq_sink/README.md b/core/connectors/sinks/rabbitmq_sink/README.md
new file mode 100644
index 000000000..28a8ffd05
--- /dev/null
+++ b/core/connectors/sinks/rabbitmq_sink/README.md
@@ -0,0 +1,50 @@
+# RabbitMQ Sink
+
+The RabbitMQ sink connector publishes messages from Iggy streams to RabbitMQ exchanges via AMQP 0.9.1.
+
+## Configuration
+
+| Field | Type | Default | Description |
+| --- | --- | --- | --- |
+| `amqp_url` | string | `amqp://guest:guest@localhost:5672` | RabbitMQ connection URL, including credentials. Treated as a secret: never logged or serialized verbatim. |
+| `exchange` | string | `iggy_events` | Exchange name to publish to. |
+| `exchange_type` | string | `topic` | Exchange type: `direct`, `topic`, `fanout`, `headers`. |
+| `routing_key` | string | `iggy.messages` | Routing key for published messages. |
+| `durable_exchange` | bool | `true` | Declare the exchange as durable. Must match the durability of an operator-pre-created exchange, otherwise RabbitMQ closes the channel with `PRECONDITION_FAILED`. |
+| `delivery_mode` | string | `persistent` | AMQP delivery mode: `persistent` (2) or `non_persistent` (1). Persistent messages survive broker restarts when the exchange and queue are durable; it forces an fsync on publish, so non-durable topologies may prefer `non_persistent`. |
+| `include_metadata` | bool | `true` | Add `iggy_stream`, `iggy_topic`, `iggy_partition_id`, `iggy_offset` message headers. User-supplied headers are always preserved, regardless of this flag. |
+| `verbose_logging` | bool | `false` | Log each published batch at `info` level instead of `debug`. |
+| `max_retries` | u32 | `3` | Maximum transient publish retries before failing the batch. |
+| `retry_delay_secs` | u64 | `1` | Base retry delay in seconds. |
+| `max_retry_delay_secs` | u64 | `5` | Upper bound for exponential backoff. |
+| `timeout_secs` | u64 | `30` | Timeout for connection, publish, and publisher-confirmation operations. |
+
+User headers on consumed Iggy messages are forwarded as AMQP headers: string values become AMQP `LongString`, raw binary values become `ByteArray`. This allows routing through a `headers` exchange on original user headers.
+
+Publishes are confirmed via `ConfirmSelect`. With `mandatory = true`, a message with a routing key that matches no binding is returned by RabbitMQ and the batch fails with a permanent error.
+
+**Delivery guarantee:** in-request retry only. Transient failures (connection loss, `Nack`, channel exceptions,
+timeouts) are retried within a single `consume()` call up to `max_retries`, resuming at the first unconfirmed
+message. Publishes are pipelined (all messages sent, then confirmed in order), so a failure mid-batch can already
+have delivered the in-flight tail; resuming re-publishes those, so delivery is **at-least-once within a batch**.
+Because lapin does not attribute a `Basic.Return` to a specific in-flight publish, any returned message fails the
+whole batch and the connection is re-established before the next poll, so a channel with unresolved confirms is
+never reused. The connectors runtime commits the consumer offset at poll time and discards `consume()`'s return
+value, so there is no cross-poll redrive or DLQ: a failure that outlives the retry budget, or a crash mid-batch, is
+**at-most-once** across polls.
+
+```toml
+[plugin_config]
+amqp_url = "amqp://guest:guest@localhost:5672"
+exchange = "iggy_events"
+exchange_type = "topic"
+routing_key = "iggy.messages"
+durable_exchange = true
+delivery_mode = "persistent"
+include_metadata = true
+verbose_logging = false
+max_retries = 3
+retry_delay_secs = 1
+max_retry_delay_secs = 5
+timeout_secs = 30
+```
diff --git a/core/connectors/sinks/rabbitmq_sink/config.toml b/core/connectors/sinks/rabbitmq_sink/config.toml
new file mode 100644
index 000000000..4c6bbfc00
--- /dev/null
+++ b/core/connectors/sinks/rabbitmq_sink/config.toml
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+type = "sink"
+key = "rabbitmq"
+enabled = true
+version = 0
+name = "RabbitMQ sink"
+path = "../../target/release/libiggy_connector_rabbitmq_sink"
+verbose = true
+
+[[streams]]
+stream = "test_stream"
+topics = ["test_topic"]
+schema = "json"
+batch_length = 100
+poll_interval = "5ms"
+consumer_group = "rabbitmq_sink_connector"
+
+[plugin_config]
+amqp_url = "amqp://guest:guest@localhost:5672"
+exchange = "iggy_events"
+exchange_type = "topic"
+routing_key = "iggy.messages"
+durable_exchange = true
+delivery_mode = "persistent"
+include_metadata = true
+verbose_logging = false
+max_retries = 3
+retry_delay_secs = 1
+max_retry_delay_secs = 5
+timeout_secs = 30
diff --git a/core/connectors/sinks/rabbitmq_sink/src/lib.rs b/core/connectors/sinks/rabbitmq_sink/src/lib.rs
new file mode 100644
index 000000000..69504096e
--- /dev/null
+++ b/core/connectors/sinks/rabbitmq_sink/src/lib.rs
@@ -0,0 +1,783 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use async_trait::async_trait;
+use iggy::prelude::HeaderKind;
+use iggy_connector_sdk::retry::{exponential_backoff, jitter};
+use iggy_connector_sdk::{
+    ConsumedMessage, Error, MessagesMetadata, Sink, TopicMetadata, sink_connector,
+};
+use lapin::{
+    BasicProperties, Channel, Connection, ConnectionProperties, ExchangeKind,
+    options::{ConfirmSelectOptions, ExchangeDeclareOptions},
+    publisher_confirm::{Confirmation, PublisherConfirm},
+    types::{AMQPValue, ByteArray, FieldTable, ShortString},
+};
+use secrecy::{ExposeSecret, SecretString};
+use serde::{Deserialize, Serialize};
+use std::sync::atomic::{AtomicU64, Ordering};
+use std::time::Duration;
+use tokio::sync::Mutex;
+use tokio::time::timeout;
+use tracing::{debug, info, warn};
+
+sink_connector!(RabbitMQSink);
+
+#[derive(Debug)]
+struct RabbitMqState {
+    connection: Connection,
+    channel: Channel,
+}
+
+#[derive(Debug)]
+pub struct RabbitMQSink {
+    id: u32,
+    amqp_url: SecretString,
+    exchange: String,
+    exchange_type: String,
+    routing_key: String,
+    include_metadata: bool,
+    verbose: bool,
+    durable_exchange: bool,
+    delivery_mode: u8,
+    timeout: Duration,
+    state: Mutex<Option<RabbitMqState>>,
+    reconnect_lock: Mutex<()>,
+    publish_lock: Mutex<()>,
+    max_retries: u32,
+    retry_delay: Duration,
+    max_retry_delay: Duration,
+    messages_published: AtomicU64,
+    publish_errors: AtomicU64,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct RabbitMQSinkConfig {
+    #[serde(
+        default = "default_amqp_url",
+        serialize_with = "iggy_common::serde_secret::serialize_secret"
+    )]
+    amqp_url: SecretString,
+    #[serde(default)]
+    exchange: Option<String>,
+    #[serde(default = "default_exchange_type")]
+    exchange_type: Option<String>,
+    #[serde(default)]
+    routing_key: Option<String>,
+    #[serde(default = "default_true")]
+    include_metadata: Option<bool>,
+    #[serde(default)]
+    verbose_logging: Option<bool>,
+    #[serde(default = "default_max_retries")]
+    max_retries: Option<u32>,
+    #[serde(default = "default_retry_delay_secs")]
+    retry_delay_secs: Option<u64>,
+    #[serde(default = "default_max_retry_delay_secs")]
+    max_retry_delay_secs: Option<u64>,
+    #[serde(default = "default_true")]
+    durable_exchange: Option<bool>,
+    #[serde(default = "default_delivery_mode")]
+    delivery_mode: Option<String>,
+    #[serde(default = "default_timeout_secs")]
+    timeout_secs: Option<u64>,
+}
+
+fn default_exchange_type() -> Option<String> {
+    Some("topic".into())
+}
+
+fn default_amqp_url() -> SecretString {
+    SecretString::from("amqp://guest:guest@localhost:5672")
+}
+
+fn default_delivery_mode() -> Option<String> {
+    Some("persistent".into())
+}
+
+fn default_timeout_secs() -> Option<u64> {
+    Some(30)
+}
+
+fn append_connection_timeout(amqp_url: &SecretString, timeout_secs: u64) -> SecretString {
+    let timeout_ms = timeout_secs * 1000;
+    let url = amqp_url.expose_secret();
+    let separator = if url.contains('?') { '&' } else { '?' };
+    SecretString::from(format!("{url}{separator}connection_timeout={timeout_ms}"))
+}
+
+fn default_true() -> Option<bool> {
+    Some(true)
+}
+
+fn default_max_retries() -> Option<u32> {
+    Some(3)
+}
+fn default_retry_delay_secs() -> Option<u64> {
+    Some(1)
+}
+fn default_max_retry_delay_secs() -> Option<u64> {
+    Some(5)
+}
+
+impl RabbitMQSink {
+    pub fn new(id: u32, config: RabbitMQSinkConfig) -> Self {
+        let delivery_mode = match config.delivery_mode.as_deref() {
+            Some("non_persistent") => 1,
+            Some("persistent") => 2,
+            Some(other) => {
+                warn!(
+                    "Unknown delivery_mode: {other}, defaulting to persistent for connector ID: {id}"
+                );
+                2
+            }
+            None => 2,
+        };
+        let timeout_secs = match config.timeout_secs {
+            Some(0) | None => {
+                if config.timeout_secs == Some(0) {
+                    warn!("timeout_secs must be >= 1, defaulting to 30 for connector ID: {id}");
+                }
+                30
+            }
+            Some(secs) => secs,
+        };
+        let amqp_url = append_connection_timeout(&config.amqp_url, timeout_secs);
+        RabbitMQSink {
+            id,
+            amqp_url,
+            exchange: config.exchange.unwrap_or_else(|| "iggy_events".into()),
+            exchange_type: config.exchange_type.unwrap_or_else(|| "topic".into()),
+            routing_key: config.routing_key.unwrap_or_else(|| "iggy.messages".into()),
+            include_metadata: config.include_metadata.unwrap_or(true),
+            verbose: config.verbose_logging.unwrap_or(false),
+            durable_exchange: config.durable_exchange.unwrap_or(true),
+            delivery_mode,
+            timeout: Duration::from_secs(timeout_secs),
+            state: Mutex::new(None),
+            reconnect_lock: Mutex::new(()),
+            publish_lock: Mutex::new(()),
+            max_retries: config.max_retries.unwrap_or(3),
+            retry_delay: Duration::from_secs(config.retry_delay_secs.unwrap_or(1)),
+            max_retry_delay: Duration::from_secs(config.max_retry_delay_secs.unwrap_or(5)),
+            messages_published: AtomicU64::new(0),
+            publish_errors: AtomicU64::new(0),
+        }
+    }
+
+    fn exchange_kind(&self) -> Result<ExchangeKind, Error> {
+        match self.exchange_type.as_str() {
+            "direct" => Ok(ExchangeKind::Direct),
+            "topic" => Ok(ExchangeKind::Topic),
+            "fanout" => Ok(ExchangeKind::Fanout),
+            "headers" => Ok(ExchangeKind::Headers),
+            other => Err(Error::InvalidConfigValue(format!(
+                "unknown exchange_type: {other}. Valid: direct, topic, fanout, headers"
+            ))),
+        }
+    }
+
+    async fn publish_batch_with_retry(
+        &self,
+        topic_metadata: &TopicMetadata,
+        messages_metadata: &MessagesMetadata,
+        messages: &[ConsumedMessage],
+    ) -> Result<u64, Error> {
+        // The connectors runtime runs one consume task per (stream, topic) pair against a
+        // single sink instance, so batches would otherwise interleave on the shared channel.
+        // Serialize them: a Basic.Return staples to whichever confirm resolves next, and with
+        // two publishers in flight it can land on the other task's confirm, letting this batch
+        // count a returned message as delivered.
+        let _publish_guard = self.publish_lock.lock().await;
+        let mut attempts = 0u32;
+        let mut confirmed: usize = 0;
+
+        loop {
+            let channel = match self
+                .state
+                .lock()
+                .await
+                .as_ref()
+                .map(|state| state.channel.clone())
+            {
+                Some(channel) => channel,
+                None => {
+                    let error = Error::Connection("RabbitMQ not connected".into());
+                    attempts += 1;
+                    if attempts >= self.max_retries {
+                        self.publish_errors
+                            .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed);
+                        return Err(error);
+                    }
+                    if let Err(reconnect_error) = self.reconnect().await {
+                        self.publish_errors
+                            .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed);
+                        return Err(Error::Connection(format!(
+                            "failed to reconnect: {reconnect_error}"
+                        )));
+                    }
+                    let delay = jitter(exponential_backoff(
+                        self.retry_delay,
+                        attempts.saturating_sub(1),
+                        self.max_retry_delay,
+                    ));
+                    warn!(
+                        "RabbitMQ not connected for connector ID: {} (attempt {attempts}/{}). Retrying in {:?}.",
+                        self.id, self.max_retries, delay
+                    );
+                    tokio::time::sleep(delay).await;
+                    continue;
+                }
+            };
+
+            let mut last_error: Option<Error> = None;
+            let mut last_retryable = false;
+            let mut in_flight: Vec<PublisherConfirm> =
+                Vec::with_capacity(messages.len() - confirmed);
+            for message in &messages[confirmed..] {
+                let body = match message.payload.try_to_bytes() {
+                    Ok(body) => body,
+                    Err(error) => {
+                        // Earlier publishes in this attempt are still in flight; drop the
+                        // channel so their orphaned confirms never leak onto a reused one.
+                        self.clear_state().await;
+                        self.publish_errors
+                            .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed);
+                        return Err(error);
+                    }
+                };
+                let mut props = BasicProperties::default().with_delivery_mode(self.delivery_mode);
+                let headers = self.build_headers(topic_metadata, messages_metadata, message);
+                if !headers.inner().is_empty() {
+                    props = props.with_headers(headers);
+                }
+
+                let confirm = match timeout(
+                    self.timeout,
+                    channel.basic_publish(
+                        &self.exchange,
+                        &self.routing_key,
+                        lapin::options::BasicPublishOptions {
+                            mandatory: true,
+                            ..Default::default()
+                        },
+                        &body,
+                        props,
+                    ),
+                )
+                .await
+                {
+                    Ok(Ok(confirm)) => confirm,
+                    Ok(Err(e)) => {
+                        last_error = Some(Error::CannotStoreData(e.to_string()));
+                        last_retryable = is_lapin_error_retryable(&e);
+                        self.clear_state().await;
+                        break;
+                    }
+                    Err(_) => {
+                        last_error = Some(Error::CannotStoreData("publish timed out".into()));
+                        last_retryable = true;
+                        self.clear_state().await;
+                        break;
+                    }
+                };
+                in_flight.push(confirm);
+            }
+
+            // Confirms resolve in publish order over already-overlapped RTTs.
+            // lapin staples a Basic.Return to whichever confirm resolves next, so under
+            // multiple-ack the returned message is not attributable to a specific publish:
+            // on any return the whole batch fails and the channel is cleared so a channel
+            // with unresolved confirms is never reused (a later batch could otherwise
+            // swallow the return and count the unroutable message as delivered).
+            for confirm in in_flight {
+                match timeout(self.timeout, confirm).await {
+                    Ok(Ok(Confirmation::Ack(None))) => confirmed += 1,
+                    Ok(Ok(Confirmation::Ack(Some(_)))) => {
+                        last_error = Some(Error::InvalidRecordValue(
+                            "message returned as unroutable by RabbitMQ".into(),
+                        ));
+                        last_retryable = false;
+                        self.clear_state().await;
+                        break;
+                    }
+                    Ok(Ok(Confirmation::Nack(_))) => {
+                        last_error =
+                            Some(Error::CannotStoreData("message nack'd by RabbitMQ".into()));
+                        last_retryable = true;
+                        self.clear_state().await;
+                        break;
+                    }
+                    Ok(Ok(Confirmation::NotRequested)) => {
+                        last_error = Some(Error::CannotStoreData(
+                            "publisher confirms not enabled".into(),
+                        ));
+                        last_retryable = false;
+                        self.clear_state().await;
+                        break;
+                    }
+                    Ok(Err(e)) => {
+                        last_error = Some(Error::CannotStoreData(format!("publish rejected: {e}")));
+                        last_retryable = is_lapin_error_retryable(&e);
+                        self.clear_state().await;
+                        break;
+                    }
+                    Err(_) => {
+                        last_error = Some(Error::CannotStoreData(
+                            "publisher confirmation timed out".into(),
+                        ));
+                        last_retryable = true;
+                        self.clear_state().await;
+                        break;
+                    }
+                }
+            }
+
+            if last_error.is_none() {
+                return Ok(confirmed as u64);
+            }
+
+            let error = last_error.unwrap();
+            attempts += 1;
+
+            if !last_retryable || attempts >= self.max_retries {
+                self.publish_errors
+                    .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed);
+                return Err(Error::CannotStoreData(format!(
+                    "batch publish failed after {attempts} attempts: {error}"
+                )));
+            }
+
+            match self.reconnect().await {
+                Ok(_) => {}
+                Err(reconnect_error) => {
+                    self.publish_errors
+                        .fetch_add((messages.len() - confirmed) as u64, Ordering::Relaxed);
+                    return Err(Error::Connection(format!(
+                        "failed to reconnect: {reconnect_error}"
+                    )));
+                }
+            }
+
+            let delay = jitter(exponential_backoff(
+                self.retry_delay,
+                attempts.saturating_sub(1),
+                self.max_retry_delay,
+            ));
+            warn!(
+                "Transient RabbitMQ publish error for connector ID: {} (attempt {attempts}/{}): {error}. Retrying in {:?}.",
+                self.id, self.max_retries, delay
+            );
+            tokio::time::sleep(delay).await;
+        }
+    }
+
+    async fn clear_state(&self) {
+        *self.state.lock().await = None;
+    }
+
+    fn build_headers(
+        &self,
+        topic_metadata: &TopicMetadata,
+        messages_metadata: &MessagesMetadata,
+        message: &ConsumedMessage,
+    ) -> FieldTable {
+        let mut headers = FieldTable::default();
+        if let Some(user_headers) = &message.headers
+            && !user_headers.is_empty()
+        {
+            for (key, value) in user_headers {
+                let name = ShortString::from(key.to_string_value());
+                let amqp_value = match value.kind() {
+                    HeaderKind::String => AMQPValue::LongString(value.to_string_value().into()),
+                    _ => AMQPValue::ByteArray(ByteArray::from(value.as_bytes())),
+                };
+                headers.insert(name, amqp_value);
+            }
+        }
+        if self.include_metadata {
+            headers.insert(
+                "iggy_stream".into(),
+                AMQPValue::LongString(topic_metadata.stream.clone().into()),
+            );
+            headers.insert(
+                "iggy_topic".into(),
+                AMQPValue::LongString(topic_metadata.topic.clone().into()),
+            );
+            headers.insert(
+                "iggy_partition_id".into(),
+                AMQPValue::LongUInt(messages_metadata.partition_id),
+            );
+            headers.insert(
+                "iggy_offset".into(),
+                AMQPValue::LongLongInt(message.offset as i64),
+            );
+        }
+        headers
+    }
+
+    async fn reconnect(&self) -> Result<(), Error> {
+        let _guard = self.reconnect_lock.lock().await;
+        if self.state.lock().await.is_some() {
+            return Ok(());
+        }
+        warn!("Reconnecting RabbitMQ sink ID: {}", self.id);
+        let state = self.connect_with_timeout().await?;
+        *self.state.lock().await = Some(state);
+        Ok(())
+    }
+
+    async fn connect_with_timeout(&self) -> Result<RabbitMqState, Error> {
+        timeout(self.timeout, self.establish_connection())
+            .await
+            .map_err(|_| Error::Connection("connection setup timed out".into()))?
+    }
+
+    async fn establish_connection(&self) -> Result<RabbitMqState, Error> {
+        let connection = Connection::connect(
+            self.amqp_url.expose_secret(),
+            ConnectionProperties::default(),
+        )
+        .await
+        .map_err(|e| Error::Connection(e.to_string()))?;
+        let channel = connection
+            .create_channel()
+            .await
+            .map_err(|e| Error::Connection(e.to_string()))?;
+        channel
+            .confirm_select(ConfirmSelectOptions::default())
+            .await
+            .map_err(|e| Error::Connection(e.to_string()))?;
+        let exchange_kind = self.exchange_kind()?;
+        channel
+            .exchange_declare(
+                &self.exchange,
+                exchange_kind,
+                ExchangeDeclareOptions {
+                    durable: self.durable_exchange,
+                    ..Default::default()
+                },
+                FieldTable::default(),
+            )
+            .await
+            .map_err(|e| Error::Connection(e.to_string()))?;
+        Ok(RabbitMqState {
+            connection,
+            channel,
+        })
+    }
+}
+
+#[async_trait]
+impl Sink for RabbitMQSink {
+    async fn open(&mut self) -> Result<(), Error> {
+        self.exchange_kind()?;
+        let state = self.connect_with_timeout().await?;
+        *self.state.get_mut() = Some(state);
+        info!(
+            "Opened RabbitMQ sink ID: {}, connected to exchange: {}",
+            self.id, self.exchange
+        );
+
+        Ok(())
+    }
+
+    async fn consume(
+        &self,
+        topic_metadata: &TopicMetadata,
+        messages_metadata: MessagesMetadata,
+        messages: Vec<ConsumedMessage>,
+    ) -> Result<(), Error> {
+        let published = self
+            .publish_batch_with_retry(topic_metadata, &messages_metadata, &messages)
+            .await?;
+        self.messages_published
+            .fetch_add(published, Ordering::Relaxed);
+        if self.verbose {
+            info!(
+                "Published {published} messages to exchange: {}",
+                self.exchange
+            );
+        } else {
+            debug!(
+                "Published {published} messages to exchange: {}",
+                self.exchange
+            );
+        }
+        Ok(())
+    }
+
+    async fn close(&mut self) -> Result<(), Error> {
+        let published = self.messages_published.load(Ordering::Relaxed);
+        let errors = self.publish_errors.load(Ordering::Relaxed);
+        info!(
+            "RabbitMQ sink ID: {} processed {} messages with {} errors",
+            self.id, published, errors
+        );
+
+        if let Some(state) = self.state.get_mut().take() {
+            state
+                .channel
+                .close(200, "OK")
+                .await
+                .map_err(|e| Error::Connection(e.to_string()))?;
+            state
+                .connection
+                .close(200, "OK")
+                .await
+                .map_err(|e| Error::Connection(e.to_string()))?;
+        }
+        Ok(())
+    }
+}
+
+fn is_lapin_error_retryable(error: &lapin::Error) -> bool {
+    match error {
+        lapin::Error::InvalidChannelState(_)
+        | lapin::Error::InvalidConnectionState(_)
+        | lapin::Error::IOError(_)
+        | lapin::Error::MissingHeartbeatError => true,
+        // AMQP soft channel errors: 405 RESOURCE_LOCKED, 320 CONNECTION_FORCED.
+        lapin::Error::ProtocolError(amqp_error) => matches!(amqp_error.get_id(), 320 | 405),
+        _ => false,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use iggy::prelude::{HeaderKey, HeaderValue};
+    use iggy_connector_sdk::{Payload, Schema};
+    use std::str::FromStr;
+
+    fn test_config() -> RabbitMQSinkConfig {
+        RabbitMQSinkConfig {
+            amqp_url: SecretString::from("amqp://guest:guest@localhost:5672"),
+            exchange: None,
+            exchange_type: None,
+            routing_key: None,
+            include_metadata: Some(true),
+            verbose_logging: Some(false),
+            max_retries: Some(3),
+            retry_delay_secs: Some(1),
+            max_retry_delay_secs: Some(5),
+            durable_exchange: None,
+            delivery_mode: None,
+            timeout_secs: None,
+        }
+    }
+
+    fn test_sink(config: RabbitMQSinkConfig) -> RabbitMQSink {
+        RabbitMQSink::new(1, config)
+    }
+
+    fn test_message(offset: u64) -> ConsumedMessage {
+        ConsumedMessage {
+            id: 1,
+            offset,
+            checksum: 0,
+            timestamp: 0,
+            origin_timestamp: 0,
+            headers: None,
+            payload: Payload::Text("payload".into()),
+        }
+    }
+
+    #[test]
+    fn given_offset_above_u32_max_when_build_headers_should_encode_full_value() {
+        let sink = test_sink(test_config());
+        let topic = TopicMetadata {
+            stream: "test_stream".into(),
+            topic: "test_topic".into(),
+        };
+        let metadata = MessagesMetadata {
+            partition_id: 0,
+            current_offset: 0,
+            schema: Schema::Json,
+        };
+        let headers = sink.build_headers(&topic, &metadata, &test_message(u32::MAX as u64 + 1));
+        match headers.inner().get(&ShortString::from("iggy_offset")) {
+            Some(AMQPValue::LongLongInt(value)) => assert_eq!(*value, u32::MAX as i64 + 1),
+            other => panic!("expected LongLongInt, got {other:?}"),
+        }
+    }
+
+    #[test]
+    fn given_user_headers_when_build_headers_should_preserve_string_and_binary() {
+        let mut user_headers = std::collections::BTreeMap::new();
+        user_headers.insert(
+            HeaderKey::from_str("content-type").unwrap(),
+            HeaderValue::from_str("application/json").unwrap(),
+        );
+        user_headers.insert(
+            HeaderKey::from_str("trace-id").unwrap(),
+            HeaderValue::try_from(vec![0xDE, 0xAD, 0xBE, 0xEF]).unwrap(),
+        );
+        let mut message = test_message(0);
+        message.headers = Some(user_headers);
+
+        let sink = test_sink(test_config());
+        let topic = TopicMetadata {
+            stream: "test_stream".into(),
+            topic: "test_topic".into(),
+        };
+        let metadata = MessagesMetadata {
+            partition_id: 0,
+            current_offset: 0,
+            schema: Schema::Json,
+        };
+        let headers = sink.build_headers(&topic, &metadata, &message);
+        let inner = headers.inner();
+        assert!(matches!(
+            inner.get(&ShortString::from("content-type")),
+            Some(AMQPValue::LongString(s)) if s.as_bytes() == b"application/json"
+        ));
+        assert!(matches!(
+            inner.get(&ShortString::from("trace-id")),
+            Some(AMQPValue::ByteArray(b)) if b.as_slice() == [0xDE, 0xAD, 0xBE, 0xEF]
+        ));
+    }
+
+    #[test]
+    fn given_persistent_delivery_mode_when_new_should_set_delivery_mode_2() {
+        let sink = test_sink(test_config());
+        assert_eq!(sink.delivery_mode, 2);
+    }
+
+    #[test]
+    fn given_non_persistent_delivery_mode_when_new_should_set_delivery_mode_1() {
+        let mut config = test_config();
+        config.delivery_mode = Some("non_persistent".into());
+        let sink = test_sink(config);
+        assert_eq!(sink.delivery_mode, 1);
+    }
+
+    #[test]
+    fn given_durable_exchange_when_new_should_default_to_true() {
+        let sink = test_sink(test_config());
+        assert!(sink.durable_exchange);
+    }
+
+    #[test]
+    fn given_known_exchange_type_when_exchange_kind_should_map_to_lapin_kind() {
+        let sink = test_sink(test_config());
+        assert!(matches!(sink.exchange_kind(), Ok(ExchangeKind::Topic)));
+    }
+
+    #[test]
+    fn given_unknown_exchange_type_when_exchange_kind_should_error() {
+        let mut config = test_config();
+        config.exchange_type = Some("mystery".into());
+        let sink = test_sink(config);
+        assert!(matches!(
+            sink.exchange_kind(),
+            Err(Error::InvalidConfigValue(_))
+        ));
+    }
+
+    #[test]
+    fn given_transient_lapin_error_when_is_lapin_error_retryable_should_return_true() {
+        let errors = [
+            lapin::Error::InvalidChannelState(lapin::ChannelState::Closed),
+            lapin::Error::InvalidConnectionState(lapin::ConnectionState::Error),
+            lapin::Error::IOError(std::sync::Arc::new(std::io::Error::new(
+                std::io::ErrorKind::ConnectionReset,
+                "reset by peer",
+            ))),
+            lapin::Error::MissingHeartbeatError,
+            lapin::Error::ProtocolError(lapin::protocol::AMQPError::new(
+                lapin::protocol::AMQPErrorKind::Soft(
+                    lapin::protocol::AMQPSoftError::RESOURCELOCKED,
+                ),
+                "RESOURCE_LOCKED".into(),
+            )),
+        ];
+        for error in errors {
+            assert!(
+                is_lapin_error_retryable(&error),
+                "expected {error:?} to be retryable"
+            );
+        }
+    }
+
+    #[test]
+    fn given_permanent_lapin_error_when_is_lapin_error_retryable_should_return_false() {
+        let errors = [
+            lapin::Error::ProtocolError(lapin::protocol::AMQPError::new(
+                lapin::protocol::AMQPErrorKind::Soft(
+                    lapin::protocol::AMQPSoftError::PRECONDITIONFAILED,
+                ),
+                "PRECONDITION_FAILED".into(),
+            )),
+            lapin::Error::InvalidChannel(0),
+        ];
+        for error in errors {
+            assert!(
+                !is_lapin_error_retryable(&error),
+                "expected {error:?} to be permanent"
+            );
+        }
+    }
+
+    #[test]
+    fn given_timeout_secs_when_new_should_set_timeout() {
+        let mut config = test_config();
+        config.timeout_secs = Some(7);
+        let sink = test_sink(config);
+        assert_eq!(sink.timeout, Duration::from_secs(7));
+    }
+
+    #[test]
+    fn given_zero_timeout_secs_when_new_should_default_to_30() {
+        let mut config = test_config();
+        config.timeout_secs = Some(0);
+        let sink = test_sink(config);
+        assert_eq!(sink.timeout, Duration::from_secs(30));
+        assert!(
+            sink.amqp_url
+                .expose_secret()
+                .ends_with("connection_timeout=30000")
+        );
+    }
+
+    #[test]
+    fn given_minimal_config_when_deserialized_should_apply_defaults() {
+        let config: RabbitMQSinkConfig = serde_json::from_str("{}").unwrap();
+        let sink = RabbitMQSink::new(1, config);
+        assert_eq!(
+            sink.amqp_url.expose_secret(),
+            "amqp://guest:guest@localhost:5672?connection_timeout=30000"
+        );
+        assert_eq!(sink.exchange, "iggy_events");
+        assert_eq!(sink.exchange_type, "topic");
+        assert_eq!(sink.routing_key, "iggy.messages");
+        assert!(sink.include_metadata);
+        assert!(sink.durable_exchange);
+        assert_eq!(sink.delivery_mode, 2);
+        assert_eq!(sink.max_retries, 3);
+        assert_eq!(sink.retry_delay, Duration::from_secs(1));
+        assert_eq!(sink.max_retry_delay, Duration::from_secs(5));
+        assert_eq!(sink.timeout, Duration::from_secs(30));
+    }
+
+    #[test]
+    fn given_unknown_delivery_mode_when_new_should_default_to_persistent() {
+        let mut config = test_config();
+        config.delivery_mode = Some("fancy".into());
+        let sink = test_sink(config);
+        assert_eq!(sink.delivery_mode, 2);
+    }
+}
diff --git a/core/integration/Cargo.toml b/core/integration/Cargo.toml
index 0450fa306..c4d500874 100644
--- a/core/integration/Cargo.toml
+++ b/core/integration/Cargo.toml
@@ -71,6 +71,7 @@ iggy_connector_sdk = { workspace = true, features = ["api"] }
 journal = { workspace = true }
 jsonwebtoken = { workspace = true }
 keyring-core = { workspace = true }
+lapin = { workspace = true }
 lazy_static = { workspace = true }
 libc = { workspace = true }
 mongodb = { workspace = true }
diff --git a/core/integration/tests/connectors/fixtures/mod.rs b/core/integration/tests/connectors/fixtures/mod.rs
index e9d7a1332..af9eb5299 100644
--- a/core/integration/tests/connectors/fixtures/mod.rs
+++ b/core/integration/tests/connectors/fixtures/mod.rs
@@ -28,6 +28,7 @@ mod meilisearch;
 mod mongodb;
 mod postgres;
 mod quickwit;
+mod rabbitmq;
 mod redshift;
 mod s3;
 mod surrealdb;
@@ -83,6 +84,11 @@ pub use postgres::{
     PostgresSourceOps,
 };
 pub use quickwit::{QuickwitFixture, QuickwitOps, QuickwitPreCreatedFixture};
+pub use rabbitmq::{
+    RabbitMqOps, RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture,
+    RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture,
+    RabbitMqSinkWithoutMetadataFixture,
+};
 pub use redshift::{
     RedshiftSinkFixture, RedshiftSinkJsonFixture, RedshiftSinkNoArchiveFixture,
     RedshiftSinkVarbyteFixture,
diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/container.rs b/core/integration/tests/connectors/fixtures/rabbitmq/container.rs
new file mode 100644
index 000000000..386460449
--- /dev/null
+++ b/core/integration/tests/connectors/fixtures/rabbitmq/container.rs
@@ -0,0 +1,327 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::connectors::fixtures;
+use futures::StreamExt;
+use integration::harness::TestBinaryError;
+use lapin::{
+    Connection, ConnectionProperties, ExchangeKind,
+    options::{BasicConsumeOptions, ExchangeDeclareOptions, QueueBindOptions, QueueDeclareOptions},
+    types::{AMQPValue, FieldTable},
+};
+use std::time::Duration;
+use testcontainers_modules::testcontainers::core::{IntoContainerPort, WaitFor};
+use testcontainers_modules::testcontainers::runners::AsyncRunner;
+use testcontainers_modules::testcontainers::{ContainerAsync, GenericImage, ImageExt};
+use tokio::time::sleep;
+use tracing::info;
+use uuid::Uuid;
+
+const RABBITMQ_IMAGE: &str = "docker.io/rabbitmq";
+const RABBITMQ_TAG: &str = "4.0-management";
+const RABBITMQ_PORT: u16 = 5672;
+const RABBITMQ_READY_MSG: &str = "Time to start RabbitMQ:";
+const RABBITMQ_BOOT_ATTEMPTS: usize = 60;
+const RABBITMQ_BOOT_INTERVAL_MS: u64 = 1000;
+
+pub(super) const DEFAULT_TEST_STREAM: &str = "test_stream";
+pub(super) const DEFAULT_TEST_TOPIC: &str = "test_topic";
+pub(super) const DEFAULT_EXCHANGE: &str = "iggy_events";
+pub(super) const DEFAULT_EXCHANGE_TYPE: &str = "topic";
+pub(super) const DEFAULT_ROUTING_KEY: &str = "iggy.messages";
+pub(super) const DEFAULT_CONSUMER_GROUP: &str = "rabbitmq_sink_test_cg";
+
+pub(super) const ENV_SINK_AMQP_URL: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_AMQP_URL";
+pub(super) const ENV_SINK_EXCHANGE: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_EXCHANGE";
+pub(super) const ENV_SINK_EXCHANGE_TYPE: &str =
+    "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_EXCHANGE_TYPE";
+pub(super) const ENV_SINK_ROUTING_KEY: &str =
+    "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_ROUTING_KEY";
+pub(super) const ENV_SINK_STREAMS_0_STREAM: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_STREAM";
+pub(super) const ENV_SINK_STREAMS_0_TOPICS: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_TOPICS";
+pub(super) const ENV_SINK_STREAMS_0_SCHEMA: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_SCHEMA";
+pub(super) const ENV_SINK_STREAMS_0_CONSUMER_GROUP: &str =
+    "IGGY_CONNECTORS_SINK_RABBITMQ_STREAMS_0_CONSUMER_GROUP";
+pub(super) const ENV_SINK_PATH: &str = "IGGY_CONNECTORS_SINK_RABBITMQ_PATH";
+pub(super) const ENV_SINK_INCLUDE_METADATA: &str =
+    "IGGY_CONNECTORS_SINK_RABBITMQ_PLUGIN_CONFIG_INCLUDE_METADATA";
+
+#[derive(PartialEq)]
+pub(super) enum RabbitMqExchangeSetup {
+    Topic,
+    Fanout,
+    Direct,
+    Headers,
+}
+pub struct RabbitMqContainer {
+    #[allow(dead_code)]
+    container: ContainerAsync<GenericImage>,
+    pub(super) amqp_url: String,
+    pub(super) queue_names: Vec<String>,
+    pub(super) exchange_setup: RabbitMqExchangeSetup,
+}
+
+impl RabbitMqContainer {
+    async fn start_container() -> Result<(ContainerAsync<GenericImage>, String), TestBinaryError> {
+        let container = GenericImage::new(RABBITMQ_IMAGE, RABBITMQ_TAG)
+            .with_exposed_port(RABBITMQ_PORT.tcp())
+            .with_wait_for(WaitFor::message_on_stdout(RABBITMQ_READY_MSG))
+            .with_mapped_port(0, RABBITMQ_PORT.tcp())
+            .with_container_name(fixtures::unique_container_name("rabbitmq"))
+            .start()
+            .await
+            .map_err(|e| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: format!("Failed to start container: {e}"),
+            })?;
+
+        let mapped_port = container
+            .ports()
+            .await
+            .map_err(|e| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: format!("Failed to get ports: {e}"),
+            })?
+            .map_to_host_port_ipv4(RABBITMQ_PORT)
+            .ok_or_else(|| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: "No mapping for RabbitMQ port".to_string(),
+            })?;
+        let amqp_url = format!("amqp://guest:guest@127.0.0.1:{mapped_port}");
+        Ok((container, amqp_url))
+    }
+
+    async fn start_with(
+        exchange_setup: RabbitMqExchangeSetup,
+        queue_count: usize,
+    ) -> Result<Self, TestBinaryError> {
+        let (container, amqp_url) = Self::start_container().await?;
+        let queue_names = (0..queue_count)
+            .map(|index| format!("test_queue_{}_{}", Uuid::new_v4().simple(), index))
+            .collect();
+
+        let instance = Self {
+            container,
+            amqp_url,
+            exchange_setup,
+            queue_names,
+        };
+        instance.wait_until_ready().await?;
+
+        info!("RabbitMQ container available at {}", instance.amqp_url);
+        Ok(instance)
+    }
+
+    pub(super) async fn start() -> Result<Self, TestBinaryError> {
+        Self::start_with(RabbitMqExchangeSetup::Topic, 1).await
+    }
+
+    pub(super) async fn start_fanout() -> Result<Self, TestBinaryError> {
+        Self::start_with(RabbitMqExchangeSetup::Fanout, 2).await
+    }
+
+    pub(super) async fn start_direct() -> Result<Self, TestBinaryError> {
+        Self::start_with(RabbitMqExchangeSetup::Direct, 1).await
+    }
+
+    pub(super) async fn start_headers() -> Result<Self, TestBinaryError> {
+        Self::start_with(RabbitMqExchangeSetup::Headers, 1).await
+    }
+
+    async fn wait_until_ready(&self) -> Result<(), TestBinaryError> {
+        let mut last_error = None;
+
+        for _ in 0..RABBITMQ_BOOT_ATTEMPTS {
+            match Connection::connect(&self.amqp_url, ConnectionProperties::default()).await {
+                Ok(_) => {
+                    return self.setup_exchange_and_queue().await;
+                }
+                Err(error) => last_error = Some(error.to_string()),
+            }
+            sleep(Duration::from_millis(RABBITMQ_BOOT_INTERVAL_MS)).await;
+        }
+
+        let detail = last_error
+            .map(|error| format!(" Last error: {error}"))
+            .unwrap_or_default();
+        Err(TestBinaryError::FixtureSetup {
+            fixture_type: "RabbitMqContainer".to_string(),
+            message: format!("RabbitMQ did not become ready.{detail}"),
+        })
+    }
+
+    async fn setup_exchange_and_queue(&self) -> Result<(), TestBinaryError> {
+        let conn = Connection::connect(&self.amqp_url, ConnectionProperties::default())
+            .await
+            .map_err(|e| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: format!("Failed to create connection for consume: {e}"),
+            })?;
+        let channel = conn
+            .create_channel()
+            .await
+            .map_err(|e| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: format!("Failed to create channel for consume: {e}"),
+            })?;
+
+        let exchange_kind = match self.exchange_setup {
+            RabbitMqExchangeSetup::Topic => ExchangeKind::Topic,
+            RabbitMqExchangeSetup::Fanout => ExchangeKind::Fanout,
+            RabbitMqExchangeSetup::Direct => ExchangeKind::Direct,
+            RabbitMqExchangeSetup::Headers => ExchangeKind::Headers,
+        };
+        channel
+            .exchange_declare(
+                DEFAULT_EXCHANGE,
+                exchange_kind,
+                ExchangeDeclareOptions {
+                    durable: true,
+                    ..Default::default()
+                },
+                FieldTable::default(),
+            )
+            .await
+            .map_err(|e| TestBinaryError::FixtureSetup {
+                fixture_type: "RabbitMqContainer".to_string(),
+                message: format!("Failed to declare exchange for consume: {e}"),
+            })?;
+
+        for queue_name in &self.queue_names {
+            channel
+                .queue_declare(
+                    queue_name,
+                    QueueDeclareOptions {
+                        auto_delete: true,
+                        ..Default::default()
+                    },
+                    FieldTable::default(),
+                )
+                .await
+                .map_err(|e| TestBinaryError::FixtureSetup {
+                    fixture_type: "RabbitMqContainer".to_string(),
+                    message: format!("Failed to create queue for consume: {e}"),
+                })?;
+
+            let mut bind_arguments = FieldTable::default();
+            if self.exchange_setup == RabbitMqExchangeSetup::Headers {
+                bind_arguments.insert("x-match".into(), AMQPValue::LongString("all".into()));
+                bind_arguments.insert("x-user".into(), AMQPValue::LongString("alice".into()));
+            }
+            channel
+                .queue_bind(
+                    queue_name,
+                    DEFAULT_EXCHANGE,
+                    DEFAULT_ROUTING_KEY,
+                    QueueBindOptions::default(),
+                    bind_arguments,
+                )
+                .await
+                .map_err(|e| TestBinaryError::FixtureSetup {
+                    fixture_type: "RabbitMqContainer".to_string(),
+                    message: format!("Failed to bind queue to exchange for consume: {e}"),
+                })?;
+        }
+
+        Ok(())
+    }
+}
+
+pub struct ConsumedDelivery {
+    pub data: Vec<u8>,
+    pub headers: lapin::types::FieldTable,
+}
+
+pub trait RabbitMqOps: Sync {
+    fn container(&self) -> &RabbitMqContainer;
+
+    fn queue_names(&self) -> &[String] {
+        &self.container().queue_names
+    }
+
+    async fn consume_messages(
+        &self,
+        count: usize,
+    ) -> Result<Vec<ConsumedDelivery>, TestBinaryError> {
+        self.consume_messages_from(&self.container().queue_names[0], count)
+            .await
+    }
+
+    async fn consume_messages_from(
+        &self,
+        queue_name: &str,
+        count: usize,
+    ) -> Result<Vec<ConsumedDelivery>, TestBinaryError> {
+        self.consume_messages_from_with_timeout(queue_name, count, Duration::from_secs(60))
+            .await
+    }
+
+    async fn consume_messages_from_with_timeout(
+        &self,
+        queue_name: &str,
+        count: usize,
+        timeout: Duration,
+    ) -> Result<Vec<ConsumedDelivery>, TestBinaryError> {
+        let conn = Connection::connect(&self.container().amqp_url, ConnectionProperties::default())
+            .await
+            .map_err(|e| TestBinaryError::InvalidState {
+                message: format!("Failed to connect to RabbitMQ for consume: {e}"),
+            })?;
+        let channel = conn
+            .create_channel()
+            .await
+            .map_err(|e| TestBinaryError::InvalidState {
+                message: format!("Failed to create channel for consume: {e}"),
+            })?;
+
+        let mut consumer = channel
+            .basic_consume(
+                queue_name,
+                "",
+                BasicConsumeOptions::default(),
+                FieldTable::default(),
+            )
+            .await
+            .map_err(|e| TestBinaryError::InvalidState {
+                message: format!("Failed to start consumer: {e}"),
+            })?;
+
+        let mut messages = Vec::with_capacity(count);
+        let deadline = tokio::time::Instant::now() + timeout;
+        while messages.len() < count && tokio::time::Instant::now() < deadline {
+            match tokio::time::timeout(Duration::from_secs(1), consumer.next()).await {
+                Ok(Some(delivery)) => {
+                    let delivery = delivery.map_err(|e| TestBinaryError::InvalidState {
+                        message: format!("Consumer error: {e}"),
+                    })?;
+                    let data = delivery.data.clone();
+                    let headers = delivery.properties.headers().clone().unwrap_or_default();
+                    delivery.ack(Default::default()).await.map_err(|e| {
+                        TestBinaryError::InvalidState {
+                            message: format!("Failed to ack message: {e}"),
+                        }
+                    })?;
+                    messages.push(ConsumedDelivery { data, headers });
+                }
+                Ok(None) => break,
+                Err(_) => continue,
+            }
+        }
+
+        Ok(messages)
+    }
+}
diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs b/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs
new file mode 100644
index 000000000..a8154b4e1
--- /dev/null
+++ b/core/integration/tests/connectors/fixtures/rabbitmq/mod.rs
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+mod container;
+mod sink;
+
+pub use container::RabbitMqOps;
+pub use sink::{
+    RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture,
+    RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture,
+    RabbitMqSinkWithoutMetadataFixture,
+};
diff --git a/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs b/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs
new file mode 100644
index 000000000..8301dacdc
--- /dev/null
+++ b/core/integration/tests/connectors/fixtures/rabbitmq/sink.rs
@@ -0,0 +1,273 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use super::container::{
+    DEFAULT_CONSUMER_GROUP, DEFAULT_EXCHANGE, DEFAULT_EXCHANGE_TYPE, DEFAULT_ROUTING_KEY,
+    DEFAULT_TEST_STREAM, DEFAULT_TEST_TOPIC, ENV_SINK_AMQP_URL, ENV_SINK_EXCHANGE,
+    ENV_SINK_EXCHANGE_TYPE, ENV_SINK_INCLUDE_METADATA, ENV_SINK_PATH, ENV_SINK_ROUTING_KEY,
+    ENV_SINK_STREAMS_0_CONSUMER_GROUP, ENV_SINK_STREAMS_0_SCHEMA, ENV_SINK_STREAMS_0_STREAM,
+    ENV_SINK_STREAMS_0_TOPICS, RabbitMqContainer, RabbitMqOps,
+};
+use async_trait::async_trait;
+use iggy_connector_sdk::Schema;
+use integration::harness::{TestBinaryError, TestFixture};
+use std::collections::HashMap;
+
+pub struct RabbitMqSinkFixture {
+    container: RabbitMqContainer,
+    include_metadata: bool,
+    schema: Schema,
+}
+
+impl RabbitMqOps for RabbitMqSinkFixture {
+    fn container(&self) -> &RabbitMqContainer {
+        &self.container
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start().await?;
+        Ok(Self {
+            container,
+            include_metadata: true,
+            schema: Schema::Json,
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        let mut envs = HashMap::new();
+        envs.insert(
+            ENV_SINK_AMQP_URL.to_string(),
+            self.container.amqp_url.clone(),
+        );
+        envs.insert(ENV_SINK_EXCHANGE.to_string(), DEFAULT_EXCHANGE.into());
+        envs.insert(
+            ENV_SINK_EXCHANGE_TYPE.to_string(),
+            DEFAULT_EXCHANGE_TYPE.into(),
+        );
+        envs.insert(ENV_SINK_ROUTING_KEY.to_string(), DEFAULT_ROUTING_KEY.into());
+        envs.insert(
+            ENV_SINK_STREAMS_0_STREAM.to_string(),
+            DEFAULT_TEST_STREAM.into(),
+        );
+        envs.insert(
+            ENV_SINK_STREAMS_0_TOPICS.to_string(),
+            format!("[{}]", DEFAULT_TEST_TOPIC),
+        );
+        envs.insert(
+            ENV_SINK_STREAMS_0_SCHEMA.to_string(),
+            self.schema.to_string(),
+        );
+        envs.insert(
+            ENV_SINK_STREAMS_0_CONSUMER_GROUP.to_string(),
+            DEFAULT_CONSUMER_GROUP.into(),
+        );
+        envs.insert(
+            ENV_SINK_PATH.to_string(),
+            "../../target/debug/libiggy_connector_rabbitmq_sink".into(),
+        );
+        envs.insert(
+            ENV_SINK_INCLUDE_METADATA.to_string(),
+            self.include_metadata.to_string(),
+        );
+        envs
+    }
+}
+
+pub struct RabbitMqSinkWithoutMetadataFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkWithoutMetadataFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkWithoutMetadataFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: false,
+                schema: Schema::Json,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        self.inner.connectors_runtime_envs()
+    }
+}
+
+pub struct RabbitMqSinkRawSchemaFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkRawSchemaFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkRawSchemaFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: true,
+                schema: Schema::Raw,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        self.inner.connectors_runtime_envs()
+    }
+}
+
+pub struct RabbitMqSinkFanoutFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkFanoutFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkFanoutFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start_fanout().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: true,
+                schema: Schema::Json,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        let mut envs = self.inner.connectors_runtime_envs();
+        envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "fanout".into());
+        envs
+    }
+}
+
+pub struct RabbitMqSinkDirectFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkDirectFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkDirectFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start_direct().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: true,
+                schema: Schema::Json,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        let mut envs = self.inner.connectors_runtime_envs();
+        envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "direct".into());
+        envs
+    }
+}
+
+pub struct RabbitMqSinkHeadersFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkHeadersFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkHeadersFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start_headers().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: true,
+                schema: Schema::Json,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        let mut envs = self.inner.connectors_runtime_envs();
+        envs.insert(ENV_SINK_EXCHANGE_TYPE.to_string(), "headers".into());
+        envs
+    }
+}
+
+pub struct RabbitMqSinkUnroutableFixture {
+    inner: RabbitMqSinkFixture,
+}
+
+impl std::ops::Deref for RabbitMqSinkUnroutableFixture {
+    type Target = RabbitMqSinkFixture;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+#[async_trait]
+impl TestFixture for RabbitMqSinkUnroutableFixture {
+    async fn setup() -> Result<Self, TestBinaryError> {
+        let container = RabbitMqContainer::start().await?;
+        Ok(Self {
+            inner: RabbitMqSinkFixture {
+                container,
+                include_metadata: true,
+                schema: Schema::Json,
+            },
+        })
+    }
+
+    fn connectors_runtime_envs(&self) -> HashMap<String, String> {
+        let mut envs = self.inner.connectors_runtime_envs();
+        envs.insert(ENV_SINK_ROUTING_KEY.to_string(), "unroutable.key".into());
+        envs
+    }
+}
diff --git a/core/integration/tests/connectors/mod.rs b/core/integration/tests/connectors/mod.rs
index f6346bcc2..54dd1437b 100644
--- a/core/integration/tests/connectors/mod.rs
+++ b/core/integration/tests/connectors/mod.rs
@@ -29,6 +29,7 @@ mod meilisearch;
 mod mongodb;
 mod postgres;
 mod quickwit;
+mod rabbitmq;
 mod random;
 mod random_source_liveness;
 mod redshift;
diff --git a/core/integration/tests/connectors/rabbitmq/mod.rs b/core/integration/tests/connectors/rabbitmq/mod.rs
new file mode 100644
index 000000000..c4a30f275
--- /dev/null
+++ b/core/integration/tests/connectors/rabbitmq/mod.rs
@@ -0,0 +1,18 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+mod rabbitmq_sink;
diff --git a/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs b/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs
new file mode 100644
index 000000000..f9c2376fb
--- /dev/null
+++ b/core/integration/tests/connectors/rabbitmq/rabbitmq_sink.rs
@@ -0,0 +1,429 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::connectors::fixtures::{
+    RabbitMqOps, RabbitMqSinkDirectFixture, RabbitMqSinkFanoutFixture, RabbitMqSinkFixture,
+    RabbitMqSinkHeadersFixture, RabbitMqSinkRawSchemaFixture, RabbitMqSinkUnroutableFixture,
+    RabbitMqSinkWithoutMetadataFixture,
+};
+use bytes::Bytes;
+use iggy::prelude::{HeaderKey, HeaderValue, IggyMessage, Partitioning};
+use iggy_common::Identifier;
+use iggy_common::MessageClient;
+use integration::harness::seeds;
+use integration::iggy_harness;
+use lapin::types::{AMQPValue, ShortString};
+use std::collections::BTreeMap;
+use std::str::FromStr;
+use std::time::Duration;
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+
+async fn json_messages_are_published_to_rabbitmq_exchange(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payloads = [
+        serde_json::json!({"name": "Alice"}),
+        serde_json::json!({"name": "Bob"}),
+        serde_json::json!({"name": "Carol"}),
+    ];
+    let mut messages: Vec<IggyMessage> = payloads
+        .iter()
+        .enumerate()
+        .map(|(idx, payload)| {
+            IggyMessage::builder()
+                .id((idx + 1) as u128)
+                .payload(Bytes::from(serde_json::to_vec(payload).unwrap()))
+                .build()
+                .unwrap()
+        })
+        .collect();
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(3).await.unwrap();
+    assert_eq!(delivered.len(), 3);
+    for (idx, delivery) in delivered.iter().enumerate() {
+        let value: serde_json::Value = serde_json::from_slice(&delivery.data).unwrap();
+        assert_eq!(value, payloads[idx]);
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_stream").as_deref(),
+            Some("test_stream")
+        );
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_topic").as_deref(),
+            Some("test_topic")
+        );
+    }
+}
+
+fn header_str(headers: &lapin::types::FieldTable, key: &str) -> Option<String> {
+    headers
+        .inner()
+        .get(&ShortString::from(key))
+        .and_then(|v| match v {
+            AMQPValue::LongString(s) => Some(s.to_string()),
+            _ => None,
+        })
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+
+async fn given_direct_exchange_when_published_should_deliver_to_bound_queue(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkDirectFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payloads = [
+        serde_json::json!({"name": "Alice"}),
+        serde_json::json!({"name": "Bob"}),
+        serde_json::json!({"name": "Carol"}),
+    ];
+    let mut messages: Vec<IggyMessage> = payloads
+        .iter()
+        .enumerate()
+        .map(|(idx, payload)| {
+            IggyMessage::builder()
+                .id((idx + 1) as u128)
+                .payload(Bytes::from(serde_json::to_vec(payload).unwrap()))
+                .build()
+                .unwrap()
+        })
+        .collect();
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(3).await.unwrap();
+    assert_eq!(delivered.len(), 3);
+    for (idx, delivery) in delivered.iter().enumerate() {
+        let value: serde_json::Value = serde_json::from_slice(&delivery.data).unwrap();
+        assert_eq!(value, payloads[idx]);
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_stream").as_deref(),
+            Some("test_stream")
+        );
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_topic").as_deref(),
+            Some("test_topic")
+        );
+    }
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_include_metadata_false_when_published_should_not_include_iggy_headers(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkWithoutMetadataFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payload = serde_json::json!({"name": "Alice"});
+    let mut messages = vec![
+        IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from(serde_json::to_vec(&payload).unwrap()))
+            .build()
+            .unwrap(),
+    ];
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(1).await.unwrap();
+    assert_eq!(delivered.len(), 1);
+    let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap();
+    assert_eq!(value, payload);
+    assert!(delivered[0].headers.inner().is_empty());
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_raw_schema_when_published_should_preserve_raw_payload_bytes(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkRawSchemaFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let raw_payloads: Vec<Vec<u8>> = vec![
+        b"plain text message".to_vec(),
+        vec![0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD],
+        vec![0xDE, 0xAD, 0xBE, 0xEF],
+    ];
+
+    let mut messages: Vec<IggyMessage> = raw_payloads
+        .iter()
+        .enumerate()
+        .map(|(idx, payload)| {
+            IggyMessage::builder()
+                .id((idx + 1) as u128)
+                .payload(Bytes::from(payload.clone()))
+                .build()
+                .unwrap()
+        })
+        .collect();
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(3).await.unwrap();
+    assert_eq!(delivered.len(), 3);
+    for (idx, delivery) in delivered.iter().enumerate() {
+        assert_eq!(delivery.data, raw_payloads[idx]);
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_stream").as_deref(),
+            Some("test_stream")
+        );
+        assert_eq!(
+            header_str(&delivery.headers, "iggy_topic").as_deref(),
+            Some("test_topic")
+        );
+    }
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_fanout_exchange_when_published_should_deliver_to_all_bound_queues(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkFanoutFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payload = serde_json::json!({"name": "Alice"});
+    let mut messages = vec![
+        IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from(serde_json::to_vec(&payload).unwrap()))
+            .build()
+            .unwrap(),
+    ];
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    assert_eq!(
+        fixture.queue_names().len(),
+        2,
+        "fanout fixture should bind two queues"
+    );
+    for queue_name in fixture.queue_names() {
+        let delivered = fixture.consume_messages_from(queue_name, 1).await.unwrap();
+        assert_eq!(
+            delivered.len(),
+            1,
+            "fanout exchange must deliver to every bound queue"
+        );
+        let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap();
+        assert_eq!(value, payload);
+        assert_eq!(
+            header_str(&delivered[0].headers, "iggy_stream").as_deref(),
+            Some("test_stream")
+        );
+        assert_eq!(
+            header_str(&delivered[0].headers, "iggy_topic").as_deref(),
+            Some("test_topic")
+        );
+    }
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_predeclared_durable_exchange_when_published_should_deliver(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payload = serde_json::json!({"name": "Alice"});
+    let mut messages = vec![
+        IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from(serde_json::to_vec(&payload).unwrap()))
+            .build()
+            .unwrap(),
+    ];
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(1).await.unwrap();
+    assert_eq!(delivered.len(), 1);
+    let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap();
+    assert_eq!(value, payload);
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_unroutable_routing_key_when_published_should_not_deliver(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkUnroutableFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let payload = serde_json::json!({"name": "Alice"});
+    let mut messages = vec![
+        IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from(serde_json::to_vec(&payload).unwrap()))
+            .build()
+            .unwrap(),
+    ];
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    tokio::time::sleep(Duration::from_secs(5)).await;
+    let delivered = fixture
+        .consume_messages_from_with_timeout(&fixture.queue_names()[0], 1, Duration::from_secs(5))
+        .await
+        .unwrap();
+    assert!(
+        delivered.is_empty(),
+        "unroutable mandatory publish must not reach any queue"
+    );
+}
+
+#[iggy_harness(
+    server(connectors_runtime(config_path = "tests/connectors/rabbitmq/sink.toml")),
+    seed = seeds::connector_stream
+)]
+async fn given_user_header_when_published_through_headers_exchange_should_route(
+    harness: &TestHarness,
+    fixture: RabbitMqSinkHeadersFixture,
+) {
+    let client = harness.root_client().await.unwrap();
+    let stream_id: Identifier = seeds::names::STREAM.try_into().unwrap();
+    let topic_id: Identifier = seeds::names::TOPIC.try_into().unwrap();
+
+    let user_headers = BTreeMap::from([(
+        HeaderKey::from_str("x-user").unwrap(),
+        HeaderValue::from_str("alice").unwrap(),
+    )]);
+    let payload = serde_json::json!({"name": "Alice"});
+    let mut messages = vec![
+        IggyMessage::builder()
+            .id(1)
+            .payload(Bytes::from(serde_json::to_vec(&payload).unwrap()))
+            .user_headers(user_headers)
+            .build()
+            .unwrap(),
+    ];
+
+    client
+        .send_messages(
+            &stream_id,
+            &topic_id,
+            &Partitioning::partition_id(0),
+            &mut messages,
+        )
+        .await
+        .unwrap();
+
+    let delivered = fixture.consume_messages(1).await.unwrap();
+    assert_eq!(delivered.len(), 1);
+    let value: serde_json::Value = serde_json::from_slice(&delivered[0].data).unwrap();
+    assert_eq!(value, payload);
+    assert_eq!(
+        header_str(&delivered[0].headers, "x-user").as_deref(),
+        Some("alice"),
+        "user header must survive to AMQP headers for headers-exchange routing"
+    );
+}
diff --git a/core/integration/tests/connectors/rabbitmq/sink.toml b/core/integration/tests/connectors/rabbitmq/sink.toml
new file mode 100644
index 000000000..e425ed503
--- /dev/null
+++ b/core/integration/tests/connectors/rabbitmq/sink.toml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[connectors]
+config_type = "local"
+config_dir = "../connectors/sinks/rabbitmq_sink"
diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh
index 88413af9d..82d278eb6 100755
--- a/scripts/bump-version.sh
+++ b/scripts/bump-version.sh
@@ -87,7 +87,7 @@ EOF
 }
 
 RUST_COMPONENTS="rust-sdk rust-common rust-binary-protocol rust-server rust-cli rust-connector-sdk rust-mcp rust-bench rust-bench-dashboard-frontend rust-bench-dashboard-server rust-bench-report"
-CONNECTOR_SINK_COMPONENTS="rust-connector-delta-sink rust-connector-elasticsearch-sink rust-connector-http-sink rust-connector-iceberg-sink rust-connector-influxdb-sink rust-connector-mongodb-sink rust-connector-postgres-sink rust-connector-quickwit-sink rust-connector-stdout-sink rust-connector-surrealdb-sink"
+CONNECTOR_SINK_COMPONENTS="rust-connector-delta-sink rust-connector-elasticsearch-sink rust-connector-http-sink rust-connector-iceberg-sink rust-connector-influxdb-sink rust-connector-mongodb-sink rust-connector-postgres-sink rust-connector-quickwit-sink rust-connector-stdout-sink rust-connector-surrealdb-sink rust-connector-rabbitmq-sink"
 CONNECTOR_SOURCE_COMPONENTS="rust-connector-elasticsearch-source rust-connector-influxdb-source rust-connector-postgres-source rust-connector-random-source"
 CONNECTOR_COMPONENTS="rust-connector-runtime ${CONNECTOR_SINK_COMPONENTS} ${CONNECTOR_SOURCE_COMPONENTS}"
 SDK_COMPONENTS="sdk-python sdk-node sdk-go sdk-csharp sdk-java"