diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml
index 097e51e636..a3f0176ff0 100644
--- a/CHANGELOG.next.toml
+++ b/CHANGELOG.next.toml
@@ -16,3 +16,15 @@ message = "EKS Pod Identity is now supported as part of the default ECS credenti
 references = ["smithy-rs#3416"]
 meta = { "breaking" = false, "bug" = false, "tada" = true }
 author = "jackkleeman"
+
+[[aws-sdk-rust]]
+message = "Added aws-smithy-wasm crate to enable SDK use in WASI compliant environments"
+references = ["smithy-rs#2087", "smithy-rs#2520", "smithy-rs#3409", "aws-sdk-rust#59"]
+meta = { "breaking" = false, "tada" = true, "bug" = false }
+author = "landonxjames"
+
+[[smithy-rs]]
+message = "Added aws-smithy-wasm crate to enable SDK use in WASI compliant environments"
+references = ["smithy-rs#2087", "smithy-rs#2520", "smithy-rs#3409"]
+meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "client"}
+author = "landonxjames"
diff --git a/aws/rust-runtime/aws-config/Cargo.toml b/aws/rust-runtime/aws-config/Cargo.toml
index bd84fc4f9c..327723871b 100644
--- a/aws/rust-runtime/aws-config/Cargo.toml
+++ b/aws/rust-runtime/aws-config/Cargo.toml
@@ -1,7 +1,10 @@
 [package]
 name = "aws-config"
 version = "0.0.0-smithy-rs-head"
-authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "Russell Cohen <rcoh@amazon.com>"]
+authors = [
+    "AWS Rust SDK Team <aws-sdk-rust@amazon.com>",
+    "Russell Cohen <rcoh@amazon.com>",
+]
 description = "AWS SDK config and credential provider implementations."
 edition = "2021"
 exclude = ["test-data/*", "integration-tests/*"]
diff --git a/aws/sdk/integration-tests/.gitignore b/aws/sdk/integration-tests/.gitignore
index 1e7caa9ea8..5f5fe6daf2 100644
--- a/aws/sdk/integration-tests/.gitignore
+++ b/aws/sdk/integration-tests/.gitignore
@@ -1,2 +1,3 @@
 Cargo.lock
 target/
+webassembly/src/bindings.rs
diff --git a/aws/sdk/integration-tests/test.sh b/aws/sdk/integration-tests/test.sh
index d26a34a116..88026f6d7c 100755
--- a/aws/sdk/integration-tests/test.sh
+++ b/aws/sdk/integration-tests/test.sh
@@ -11,6 +11,12 @@ for f in *; do
       echo
       echo "Testing ${f}..."
       echo "###############"
-      cargo test --manifest-path "${f}/Cargo.toml" --all-features
+      if [ "$f" != "webassembly" ]; then
+         cargo test --manifest-path "${f}/Cargo.toml" --all-features
+      else
+         # The webassembly tests use a custom runner set in config.toml that
+         # is not picked up when running the tests outside of the package
+         cd webassembly && cargo component test --all-features --all-targets && cd ..
+      fi
    fi
 done
diff --git a/aws/sdk/integration-tests/webassembly/.cargo/config.toml b/aws/sdk/integration-tests/webassembly/.cargo/config.toml
index 031dad7377..06b75c8e09 100644
--- a/aws/sdk/integration-tests/webassembly/.cargo/config.toml
+++ b/aws/sdk/integration-tests/webassembly/.cargo/config.toml
@@ -3,3 +3,9 @@ target = "wasm32-wasi"
 
 [target.wasm32-wasi]
 rustflags = ["-C", "opt-level=1"]
+runner = [
+    "wasmtime",
+    "-C", "cache=n",
+    "-S", "preview2=y",
+    "-S", "http=y"
+]
diff --git a/aws/sdk/integration-tests/webassembly/Cargo.toml b/aws/sdk/integration-tests/webassembly/Cargo.toml
index 379f3d8e7d..66c06fd06e 100644
--- a/aws/sdk/integration-tests/webassembly/Cargo.toml
+++ b/aws/sdk/integration-tests/webassembly/Cargo.toml
@@ -2,7 +2,9 @@
 [package]
 name = "webassembly"
 version = "0.1.0"
-authors = ["Eduardo Rodrigues <16357187+eduardomourar@users.noreply.github.com>"]
+authors = [
+    "Eduardo Rodrigues <16357187+eduardomourar@users.noreply.github.com>",
+]
 description = """
 These tests ensure that things will fail (or not fail) as expected
 when target is set to wasm32-wasi for all SDK and runtime crates.
@@ -12,20 +14,34 @@ license = "Apache-2.0"
 repository = "https://github.com/smithy-lang/smithy-rs"
 publish = false
 
-[lib]
-crate-type = ["cdylib"]
 
+[features]
+default = ["test-util"]
+test-util = []
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
-[dependencies]
-aws-config = { path = "../../build/aws-sdk/sdk/aws-config", default-features = false, features = ["rt-tokio", "behavior-version-latest"]}
+[target.'cfg(target_family = "wasm")'.dependencies]
+aws-config = { path = "../../build/aws-sdk/sdk/aws-config", default-features = false, features = [
+    "rt-tokio",
+    "behavior-version-latest"
+] }
 aws-credential-types = { path = "../../build/aws-sdk/sdk/aws-credential-types", features = ["hardcoded-credentials"] }
 aws-sdk-s3 = { path = "../../build/aws-sdk/sdk/s3", default-features = false }
 aws-smithy-http = { path = "../../build/aws-sdk/sdk/aws-smithy-http" }
 aws-smithy-runtime = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime", features = ["client"] }
 aws-smithy-runtime-api = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime-api", features = ["client"] }
 aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" }
-aws-types = { path = "../../build/aws-sdk/sdk/aws-types" }
-http = "0.2.8"
-tokio = { version = "1.24.2", features = ["macros", "rt"] }
-tower = "0.4.13"
+aws-smithy-wasm = { path = "../../build/aws-sdk/sdk/aws-smithy-wasm" }
+http = "0.2.9"
+tokio = { version = "1.32.0", features = ["macros", "rt"] }
+
+[target.'cfg(all(target_family = "wasm", target_os = "wasi"))'.dependencies]
+wit-bindgen = { version = "0.16.0", features = ["macros", "realloc"] }
+
+
+[lib]
+crate-type = ["cdylib"]
+
+# metadata used by cargo-component to identify which wit world to embed in the binary
+[package.metadata.component]
+package = "aws:component"
diff --git a/aws/sdk/integration-tests/webassembly/src/default_config.rs b/aws/sdk/integration-tests/webassembly/src/default_config.rs
deleted file mode 100644
index c87a364b5e..0000000000
--- a/aws/sdk/integration-tests/webassembly/src/default_config.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-use crate::http::WasmHttpConnector;
-use aws_config::retry::RetryConfig;
-use aws_credential_types::Credentials;
-use aws_smithy_types::timeout::TimeoutConfig;
-use aws_types::region::Region;
-use std::future::Future;
-
-pub(crate) fn get_default_config() -> impl Future<Output = aws_config::SdkConfig> {
-    aws_config::from_env()
-        .region(Region::from_static("us-west-2"))
-        .credentials_provider(Credentials::from_keys(
-            "access_key",
-            "secret_key",
-            Some("session_token".to_string()),
-        ))
-        .timeout_config(TimeoutConfig::disabled())
-        .retry_config(RetryConfig::disabled())
-        .http_client(WasmHttpConnector::new())
-        .load()
-}
-
-#[tokio::test]
-pub async fn test_default_config() {
-    let shared_config = get_default_config().await;
-    let client = aws_sdk_s3::Client::new(&shared_config);
-    assert_eq!(client.config().region().unwrap().to_string(), "us-west-2")
-}
diff --git a/aws/sdk/integration-tests/webassembly/src/http.rs b/aws/sdk/integration-tests/webassembly/src/http.rs
deleted file mode 100644
index 19354d0606..0000000000
--- a/aws/sdk/integration-tests/webassembly/src/http.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-use aws_smithy_runtime_api::client::http::{
-    HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector,
-};
-use aws_smithy_runtime_api::client::orchestrator::{HttpRequest, HttpResponse};
-use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
-use aws_smithy_runtime_api::shared::IntoShared;
-use aws_smithy_types::body::SdkBody;
-
-pub(crate) fn make_request(_req: HttpRequest) -> Result<HttpResponse, ()> {
-    // Consumers here would pass the HTTP request to
-    // the Wasm host in order to get the response back
-    let body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-    <ListAllMyBucketsResult>
-    <Buckets>
-        <Bucket>
-            <CreationDate>2023-01-23T11:59:03.575496Z</CreationDate>
-            <Name>doc-example-bucket</Name>
-        </Bucket>
-        <Bucket>
-            <CreationDate>2023-01-23T23:32:13.125238Z</CreationDate>
-            <Name>doc-example-bucket2</Name>
-        </Bucket>
-    </Buckets>
-    <Owner>
-        <DisplayName>account-name</DisplayName>
-        <ID>a3a42310-42d0-46d1-9745-0cee9f4fb851</ID>
-    </Owner>
-    </ListAllMyBucketsResult>";
-    Ok(HttpResponse::try_from(http::Response::new(SdkBody::from(body))).unwrap())
-}
-
-#[derive(Default, Debug, Clone)]
-pub(crate) struct WasmHttpConnector;
-impl WasmHttpConnector {
-    pub fn new() -> Self {
-        Self
-    }
-}
-
-impl HttpConnector for WasmHttpConnector {
-    fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
-        println!("Adapter: sending request...");
-        let res = make_request(request).unwrap();
-        println!("{:?}", res);
-        HttpConnectorFuture::new(async move { Ok(res) })
-    }
-}
-
-impl HttpClient for WasmHttpConnector {
-    fn http_connector(
-        &self,
-        _settings: &HttpConnectorSettings,
-        _components: &RuntimeComponents,
-    ) -> SharedHttpConnector {
-        self.clone().into_shared()
-    }
-}
diff --git a/aws/sdk/integration-tests/webassembly/src/http_client.rs b/aws/sdk/integration-tests/webassembly/src/http_client.rs
new file mode 100644
index 0000000000..5737b0fa3a
--- /dev/null
+++ b/aws/sdk/integration-tests/webassembly/src/http_client.rs
@@ -0,0 +1,54 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+use aws_config::retry::RetryConfig;
+use aws_sdk_s3::operation::list_objects_v2::builders::ListObjectsV2FluentBuilder;
+use aws_sdk_s3::Client;
+use aws_smithy_types::timeout::TimeoutConfig;
+use aws_smithy_wasm::wasi::WasiHttpClientBuilder;
+
+pub(crate) async fn get_default_wasi_config() -> aws_config::SdkConfig {
+    let http_client = WasiHttpClientBuilder::new().build();
+    aws_config::from_env()
+        .region("us-east-2")
+        .timeout_config(TimeoutConfig::disabled())
+        .retry_config(RetryConfig::disabled())
+        .no_credentials()
+        .http_client(http_client)
+        .load()
+        .await
+}
+
+#[tokio::test]
+pub async fn test_default_config() {
+    let shared_config = get_default_wasi_config().await;
+    let client = aws_sdk_s3::Client::new(&shared_config);
+    assert_eq!(client.config().region().unwrap().to_string(), "us-east-2")
+}
+
+async fn s3_list_objects_operation() -> ListObjectsV2FluentBuilder {
+    let shared_config = get_default_wasi_config().await;
+    let client = Client::new(&shared_config);
+    let operation = client
+        .list_objects_v2()
+        .bucket("nara-national-archives-catalog")
+        .delimiter("/")
+        .prefix("authority-records/organization/")
+        .max_keys(5);
+
+    operation
+}
+
+// Test constructing an operation using an SdkConfig with a WASI http client
+// We do not send the request to keep these tests sandboxable, a full test of
+// the client is in the SDK canary.
+#[tokio::test]
+pub async fn test_operation_construction() {
+    let operation = s3_list_objects_operation().await;
+    assert_eq!(
+        operation.get_bucket(),
+        &Some("nara-national-archives-catalog".to_string())
+    );
+}
diff --git a/aws/sdk/integration-tests/webassembly/src/lib.rs b/aws/sdk/integration-tests/webassembly/src/lib.rs
index 1c4932afbb..3c29305c06 100644
--- a/aws/sdk/integration-tests/webassembly/src/lib.rs
+++ b/aws/sdk/integration-tests/webassembly/src/lib.rs
@@ -3,11 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-mod default_config;
-mod http;
-mod list_buckets;
+#![allow(dead_code)]
 
-#[tokio::main(flavor = "current_thread")]
-pub async fn main() {
-    crate::list_buckets::s3_list_buckets().await
-}
+#[cfg(target_family = "wasm")]
+mod http_client;
+#[cfg(all(target_family = "wasm", target_os = "wasi"))]
+mod wasi;
diff --git a/aws/sdk/integration-tests/webassembly/src/list_buckets.rs b/aws/sdk/integration-tests/webassembly/src/list_buckets.rs
deleted file mode 100644
index 692be0e071..0000000000
--- a/aws/sdk/integration-tests/webassembly/src/list_buckets.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-pub async fn s3_list_buckets() {
-    use aws_sdk_s3::Client;
-
-    use crate::default_config::get_default_config;
-
-    let shared_config = get_default_config().await;
-    let client = Client::new(&shared_config);
-    let result = client.list_buckets().send().await.unwrap();
-    assert_eq!(result.buckets().len(), 2)
-}
-
-#[tokio::test]
-pub async fn test_s3_list_buckets() {
-    s3_list_buckets().await
-}
diff --git a/aws/sdk/integration-tests/webassembly/src/wasi.rs b/aws/sdk/integration-tests/webassembly/src/wasi.rs
new file mode 100644
index 0000000000..fc131bc69b
--- /dev/null
+++ b/aws/sdk/integration-tests/webassembly/src/wasi.rs
@@ -0,0 +1,32 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// Needed for WASI-compliant environment as it expects specific functions
+// to be exported such as `cabi_realloc`, `_start`, etc.
+
+wit_bindgen::generate!({
+    inline: "
+        package aws:component;
+
+        interface run {
+            run: func() -> result;
+        }
+
+        world main {
+            export run;
+        }
+    ",
+    exports: {
+        "aws:component/run": Component
+    }
+});
+
+struct Component;
+
+impl exports::aws::component::run::Guest for Component {
+    fn run() -> Result<(), ()> {
+        Ok(())
+    }
+}
diff --git a/buildSrc/src/main/kotlin/CrateSet.kt b/buildSrc/src/main/kotlin/CrateSet.kt
index e3ad6e49ee..bf36433e17 100644
--- a/buildSrc/src/main/kotlin/CrateSet.kt
+++ b/buildSrc/src/main/kotlin/CrateSet.kt
@@ -70,6 +70,7 @@ object CrateSet {
             "aws-smithy-runtime-api",
             "aws-smithy-types",
             "aws-smithy-types-convert",
+            "aws-smithy-wasm",
             "aws-smithy-xml",
         ).map { Crate(it, version(it)) }
 
diff --git a/rust-runtime/Cargo.toml b/rust-runtime/Cargo.toml
index 142b137050..74d3258886 100644
--- a/rust-runtime/Cargo.toml
+++ b/rust-runtime/Cargo.toml
@@ -18,6 +18,7 @@ members = [
     "aws-smithy-runtime-api",
     "aws-smithy-types",
     "aws-smithy-types-convert",
+    "aws-smithy-wasm",
     "aws-smithy-mocks-experimental",
     "aws-smithy-xml",
 ]
diff --git a/rust-runtime/aws-smithy-wasm/Cargo.toml b/rust-runtime/aws-smithy-wasm/Cargo.toml
new file mode 100644
index 0000000000..7dc1dd4cc1
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "aws-smithy-wasm"
+version = "0.1.0"
+authors = [
+  "AWS Rust SDK Team <aws-sdk-rust@amazon.com>",
+  "Eduardo Rodrigues <16357187+eduardomourar@users.noreply.github.com>",
+]
+description = "Smithy WebAssembly configuration for smithy-rs."
+edition = "2021"
+license = "Apache-2.0"
+repository = "https://github.com/awslabs/smithy-rs"
+
+[dependencies]
+aws-smithy-runtime-api = { path = "../aws-smithy-runtime-api", features = ["http-1x"]}
+aws-smithy-http = { path = "../aws-smithy-http" }
+aws-smithy-types = { path = "../aws-smithy-types" }
+bytes = "1"
+http = "1.0.0"
+tracing = "0.1.40"
+# Note the wasi crate will only build for target wasm32-wasi, but having a target
+# statement here breaks some of the CI tests, so we leave it with the rest of the deps
+wasi = "0.12.0+wasi-0.2.0"
+
+[package.metadata.docs.rs]
+all-features = true
+targets = ["x86_64-unknown-linux-gnu"]
+cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
+rustdoc-args = ["--cfg", "docsrs"]
+# End of docs.rs metadata
diff --git a/rust-runtime/aws-smithy-wasm/LICENSE b/rust-runtime/aws-smithy-wasm/LICENSE
new file mode 100644
index 0000000000..67db858821
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/LICENSE
@@ -0,0 +1,175 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
diff --git a/rust-runtime/aws-smithy-wasm/README.md b/rust-runtime/aws-smithy-wasm/README.md
new file mode 100644
index 0000000000..5190145609
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/README.md
@@ -0,0 +1,7 @@
+# aws-smithy-wasm
+
+WebAssembly and WASI related configuration for service clients generated by [smithy-rs](https://github.com/awslabs/smithy-rs).
+
+<!-- anchor_start:footer -->
+This crate is part of the [AWS SDK for Rust](https://awslabs.github.io/aws-sdk-rust/) and the [smithy-rs](https://github.com/smithy-lang/smithy-rs) code generator. In most cases, it should not be used directly.
+<!-- anchor_end:footer -->
diff --git a/rust-runtime/aws-smithy-wasm/external-types.toml b/rust-runtime/aws-smithy-wasm/external-types.toml
new file mode 100644
index 0000000000..25256eeaba
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/external-types.toml
@@ -0,0 +1,5 @@
+allowed_external_types = [
+    "aws_smithy_runtime_api::client::http::HttpClient",
+    "aws_smithy_runtime_api::client::http::SharedHttpClient",
+    "aws_smithy_runtime_api::client::http::HttpConnector"
+]
diff --git a/rust-runtime/aws-smithy-wasm/src/lib.rs b/rust-runtime/aws-smithy-wasm/src/lib.rs
new file mode 100644
index 0000000000..84e9b7dd9f
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/src/lib.rs
@@ -0,0 +1,20 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Automatically managed default lints */
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+/* End of automatically managed default lints */
+#![allow(clippy::derive_partial_eq_without_eq)]
+#![warn(
+    missing_docs,
+    rustdoc::missing_crate_level_docs,
+    unreachable_pub,
+    rust_2018_idioms
+)]
+
+//! Smithy WebAssembly
+
+/// Tools for using Smithy SDKs in WASI environments
+pub mod wasi;
diff --git a/rust-runtime/aws-smithy-wasm/src/wasi.rs b/rust-runtime/aws-smithy-wasm/src/wasi.rs
new file mode 100644
index 0000000000..1c32d3ee94
--- /dev/null
+++ b/rust-runtime/aws-smithy-wasm/src/wasi.rs
@@ -0,0 +1,350 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//! WASI HTTP Adapter
+use aws_smithy_http::header::ParseError;
+use aws_smithy_runtime_api::{
+    client::{
+        http::{
+            HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings,
+            SharedHttpClient, SharedHttpConnector,
+        },
+        orchestrator::HttpRequest,
+        result::ConnectorError,
+        runtime_components::RuntimeComponents,
+    },
+    http::Response,
+    shared::IntoShared,
+};
+use aws_smithy_types::body::SdkBody;
+use bytes::{Bytes, BytesMut};
+use wasi::http::{
+    outgoing_handler,
+    types::{self as wasi_http, OutgoingBody, RequestOptions},
+};
+
+/// Builder for [`WasiHttpClient`]. Currently empty, but allows for future
+/// config options to be added in a backwards compatible manner.
+#[derive(Default, Debug)]
+#[non_exhaustive]
+pub struct WasiHttpClientBuilder {}
+
+impl WasiHttpClientBuilder {
+    /// Creates a new builder.
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Builds the [`WasiHttpClient`].
+    pub fn build(self) -> SharedHttpClient {
+        let client = WasiHttpClient {};
+        client.into_shared()
+    }
+}
+
+/// An HTTP client that can be used during instantiation of the client SDK in
+/// order to route the HTTP requests through the WebAssembly host. The host must
+/// support the WASI HTTP proposal as defined in the Preview 2 specification.
+#[derive(Debug, Clone)]
+#[non_exhaustive]
+pub struct WasiHttpClient {}
+
+impl HttpClient for WasiHttpClient {
+    fn http_connector(
+        &self,
+        settings: &HttpConnectorSettings,
+        _components: &RuntimeComponents,
+    ) -> SharedHttpConnector {
+        let options = WasiRequestOptions::from(settings);
+        let connector = WasiHttpConnector { options };
+
+        connector.into_shared()
+    }
+}
+
+/// HTTP connector used in WASI environment
+#[derive(Debug, Clone)]
+struct WasiHttpConnector {
+    options: WasiRequestOptions,
+}
+
+impl HttpConnector for WasiHttpConnector {
+    fn call(&self, request: HttpRequest) -> HttpConnectorFuture {
+        tracing::trace!("WasiHttpConnector: sending request {request:?}");
+
+        let client = WasiDefaultClient::new(self.options.clone());
+        let http_req = request.try_into_http1x().expect("Http request invalid");
+        let converted_req = http_req.map(|body| match body.bytes() {
+            Some(value) => Bytes::copy_from_slice(value),
+            None => Bytes::new(),
+        });
+
+        let fut_result = client.handle(converted_req);
+
+        HttpConnectorFuture::new(async move {
+            let fut = fut_result?;
+            let response = fut.map(|body| {
+                if body.is_empty() {
+                    SdkBody::empty()
+                } else {
+                    SdkBody::from(body)
+                }
+            });
+            tracing::trace!("WasiHttpConnector: response received {response:?}");
+
+            let sdk_res = Response::try_from(response)
+                .map_err(|err| ConnectorError::other(err.into(), None))?;
+
+            Ok(sdk_res)
+        })
+    }
+}
+
+/// WASI HTTP client containing the options passed to the outgoing_handler
+struct WasiDefaultClient {
+    options: WasiRequestOptions,
+}
+
+impl WasiDefaultClient {
+    /// Create a new WASI HTTP client.
+    fn new(options: WasiRequestOptions) -> Self {
+        Self { options }
+    }
+
+    /// Make outgoing HTTP request in a WASI environment
+    fn handle(&self, req: http::Request<Bytes>) -> Result<http::Response<Bytes>, ConnectorError> {
+        let req =
+            WasiRequest::try_from(req).map_err(|err| ConnectorError::other(err.into(), None))?;
+
+        let res = outgoing_handler::handle(req.0, self.options.clone().0)
+            .map_err(|err| ConnectorError::other(err.into(), None))?;
+
+        // Right now only synchronous calls can be made through WASI, so we subscribe and
+        // block on the FutureIncomingResponse
+        let subscription = res.subscribe();
+        subscription.block();
+
+        //The FutureIncomingResponse .get() method returns a
+        //Option<Result<Result<IncomingResponse, ErrorCode>, ()>>.
+        //The outer Option ensures readiness which we know is Some because we .block() waiting for it
+        //The outer Result is just a singleton enforcer so we can only get the response once
+        //The inner Result indicates whether the HTTP call was sent/received successfully (not the 200 succes of the call)
+        let incoming_res = res
+            .get()
+            .expect("Http response not ready")
+            .expect("Http response accessed more than once")
+            .map_err(|err| ConnectorError::other(err.into(), None))?;
+
+        let response = http::Response::try_from(WasiResponse(incoming_res))
+            .map_err(|err| ConnectorError::other(err.into(), None))?;
+
+        Ok(response)
+    }
+}
+
+/// Wrapper for the WASI RequestOptions type to allow us to impl Clone
+#[derive(Debug)]
+struct WasiRequestOptions(Option<outgoing_handler::RequestOptions>);
+
+impl From<&HttpConnectorSettings> for WasiRequestOptions {
+    fn from(value: &HttpConnectorSettings) -> Self {
+        //The WASI Duration is nanoseconds represented as u64
+        //Note: that the HttpConnectorSettings provides nanoseconds as u128
+        //so here we are clamping to u64::MAX if the value is above that
+        let connect_timeout = value
+            .connect_timeout()
+            .map(|dur| u64::try_from(dur.as_nanos()).unwrap_or(u64::MAX));
+        let read_timeout = value
+            .read_timeout()
+            .map(|dur| u64::try_from(dur.as_nanos()).unwrap_or(u64::MAX));
+
+        //Note: these only fail if setting this particular type of timeout is not
+        //supported. Spec compliant runtimes should always support these so it is
+        //unlikely to be an issue.
+        let wasi_http_opts = wasi_http::RequestOptions::new();
+        wasi_http_opts
+            .set_connect_timeout(connect_timeout)
+            .expect("Connect timeout not supported");
+        wasi_http_opts
+            .set_first_byte_timeout(read_timeout)
+            .expect("Read timeout not supported");
+
+        WasiRequestOptions(Some(wasi_http_opts))
+    }
+}
+//The WASI RequestOptions type doesn't impl copy or clone but the outgoing_handler::handle method
+//takes ownership, so we impl it on this wrapper type
+impl Clone for WasiRequestOptions {
+    fn clone(&self) -> Self {
+        //Note none of the expects here should ever trigger since all of the values passed in are from
+        //the existing RequestOptions that is being cloned and should be valid
+        let new_opts = if let Some(opts) = &self.0 {
+            let new_opts = RequestOptions::new();
+            new_opts
+                .set_between_bytes_timeout(opts.between_bytes_timeout())
+                .expect("Between bytes timeout");
+            new_opts
+                .set_connect_timeout(opts.connect_timeout())
+                .expect("Connect timeout");
+            new_opts
+                .set_first_byte_timeout(opts.first_byte_timeout())
+                .expect("First byte timeout");
+
+            Some(new_opts)
+        } else {
+            None
+        };
+
+        Self(new_opts)
+    }
+}
+
+/// Wrapper to allow converting between HTTP Request types and WASI Request types
+#[derive(Debug)]
+struct WasiRequest(outgoing_handler::OutgoingRequest);
+
+impl TryFrom<http::Request<Bytes>> for WasiRequest {
+    type Error = ParseError;
+
+    fn try_from(value: http::Request<Bytes>) -> Result<Self, Self::Error> {
+        let (parts, body) = value.into_parts();
+        let method = WasiMethod::try_from(parts.method)?;
+        let path_with_query = parts.uri.path_and_query().map(|path| path.as_str());
+        let headers = WasiHeaders::try_from(parts.headers)?;
+        let scheme = match parts.uri.scheme_str().unwrap_or("") {
+            "http" => Some(&wasi_http::Scheme::Http),
+            "https" => Some(&wasi_http::Scheme::Https),
+            _ => None,
+        };
+        let authority = parts.uri.authority().map(|auth| auth.as_str());
+
+        let request = wasi_http::OutgoingRequest::new(headers.0);
+        request
+            .set_scheme(scheme)
+            .map_err(|_| ParseError::new("Failed to set HTTP scheme"))?;
+        request
+            .set_method(&method.0)
+            .map_err(|_| ParseError::new("Failed to set HTTP method"))?;
+        request
+            .set_path_with_query(path_with_query)
+            .map_err(|_| ParseError::new("Failed to set HTTP path"))?;
+        request
+            .set_authority(authority)
+            .map_err(|_| ParseError::new("Failed to set HTTP authority"))?;
+
+        let request_body = request.body().expect("Body accessed more than once");
+
+        let request_stream = request_body
+            .write()
+            .expect("Output stream accessed more than once");
+
+        request_stream
+            .blocking_write_and_flush(&body)
+            .map_err(|_| ParseError::new("Failed to write HTTP body"))?;
+
+        //The OutputStream is a child resource: it must be dropped
+        //before the parent OutgoingBody resource is dropped (or finished),
+        //otherwise the OutgoingBody drop or finish will trap.
+        drop(request_stream);
+
+        OutgoingBody::finish(request_body, None)
+            .map_err(|_| ParseError::new("Failed to finalize HTTP body"))?;
+
+        Ok(WasiRequest(request))
+    }
+}
+
+/// Wrapper to allow converting between HTTP Methods and WASI Methods
+struct WasiMethod(wasi_http::Method);
+
+impl TryFrom<http::Method> for WasiMethod {
+    type Error = ParseError;
+
+    fn try_from(method: http::Method) -> Result<Self, Self::Error> {
+        Ok(Self(match method {
+            http::Method::GET => wasi_http::Method::Get,
+            http::Method::POST => wasi_http::Method::Post,
+            http::Method::PUT => wasi_http::Method::Put,
+            http::Method::DELETE => wasi_http::Method::Delete,
+            http::Method::PATCH => wasi_http::Method::Patch,
+            http::Method::CONNECT => wasi_http::Method::Connect,
+            http::Method::TRACE => wasi_http::Method::Trace,
+            http::Method::HEAD => wasi_http::Method::Head,
+            http::Method::OPTIONS => wasi_http::Method::Options,
+            _ => return Err(ParseError::new("failed due to unsupported method, currently supported methods are: GET, POST, PUT, DELETE, PATCH, CONNECT, TRACE, HEAD, and OPTIONS")),
+        }))
+    }
+}
+
+/// Wrapper to allow converting between HTTP Response types and WASI Response types
+struct WasiResponse(wasi_http::IncomingResponse);
+
+impl TryFrom<WasiResponse> for http::Response<Bytes> {
+    type Error = ParseError;
+
+    fn try_from(value: WasiResponse) -> Result<Self, Self::Error> {
+        let response = value.0;
+
+        let status = response.status();
+
+        //This headers resource is a child: it must be dropped before the parent incoming-response is dropped.
+        //The drop happens via the consuming iterator used below
+        let headers = response.headers().entries();
+
+        let res_build = headers
+            .into_iter()
+            .fold(http::Response::builder().status(status), |rb, header| {
+                rb.header(header.0, header.1)
+            });
+
+        let body_incoming = response.consume().expect("Consume called more than once");
+
+        //The input-stream resource is a child: it must be dropped before the parent
+        //incoming-body is dropped, or consumed by incoming-body.finish.
+        //That drop is done explicitly below
+        let body_stream = body_incoming
+            .stream()
+            .expect("Stream accessed more than once");
+
+        let mut body = BytesMut::new();
+
+        //blocking_read blocks until at least one byte is available
+        while let Ok(stream_bytes) = body_stream.blocking_read(u64::MAX) {
+            body.extend_from_slice(stream_bytes.as_slice())
+        }
+
+        drop(body_stream);
+
+        let res = res_build
+            .body(body.freeze())
+            .map_err(|err| ParseError::new(err.to_string()))?;
+
+        Ok(res)
+    }
+}
+
+/// Wrapper to allow converting between HTTP headers and WASI headers
+struct WasiHeaders(wasi_http::Fields);
+
+impl TryFrom<http::HeaderMap> for WasiHeaders {
+    type Error = ParseError;
+
+    fn try_from(headers: http::HeaderMap) -> Result<Self, Self::Error> {
+        let entries = headers
+            .iter()
+            .map(|(name, value)| {
+                (
+                    name.to_string(),
+                    value.to_str().unwrap().as_bytes().to_vec(),
+                )
+            })
+            .collect::<Vec<_>>();
+
+        let fields = wasi_http::Fields::from_list(&entries)
+            .map_err(|err| ParseError::new(err.to_string()))?;
+
+        Ok(Self(fields))
+    }
+}
diff --git a/tools/ci-build/Dockerfile b/tools/ci-build/Dockerfile
index d6262863c7..a6bc44128d 100644
--- a/tools/ci-build/Dockerfile
+++ b/tools/ci-build/Dockerfile
@@ -15,9 +15,9 @@ RUN yum -y updateinfo
 FROM bare_base_image as musl_toolchain
 RUN yum -y install --allowerasing tar gzip gcc make
 RUN curl https://musl.libc.org/releases/musl-1.2.3.tar.gz -o musl-1.2.3.tar.gz \
-  && ls \
-  && tar xvzf musl-1.2.3.tar.gz \
-  && (cd musl-1.2.3 && ./configure && make install)
+    && ls \
+    && tar xvzf musl-1.2.3.tar.gz \
+    && (cd musl-1.2.3 && ./configure && make install)
 
 #
 # Rust & Tools Installation Stage
@@ -121,17 +121,14 @@ ARG wasm_pack_version=0.11.0
 RUN cargo install wasm-pack --locked --version ${wasm_pack_version}
 
 FROM install_rust AS wasmtime
-ARG wasmtime_precompiled_url=https://github.com/bytecodealliance/wasmtime/releases/download/v7.0.0/wasmtime-v7.0.0-x86_64-linux.tar.xz
-ARG wasmtime_precompiled_sha256=b8a1c97f9107c885ea73a5c38677d0d340a7c26879d366e8a5f3dce84cffec99
-RUN set -eux; \
-    curl "${wasmtime_precompiled_url}" -L -o wasmtime.xz; \
-    echo "${wasmtime_precompiled_sha256} wasmtime.xz" | sha256sum --check; \
-    tar xf wasmtime.xz; \
-    mv wasmtime-v*/wasmtime /opt;
+ARG cargo_wasmtime_version=18.0.1
+ARG rust_nightly_version
+RUN cargo install wasmtime-cli --features="component-model" --locked --version ${cargo_wasmtime_version}
 
-FROM install_rust AS cargo_wasi
-ARG cargo_wasi_version=0.1.27
-RUN cargo install cargo-wasi --locked --version ${cargo_wasi_version}
+FROM install_rust AS cargo_component
+ARG cargo_component_version=0.7.1
+ARG rust_nightly_version
+RUN cargo +${rust_nightly_version} install cargo-component --locked --version ${cargo_component_version}
 
 FROM install_rust AS cargo_semver_checks
 ARG cargo_semver_checks_version=0.24.1
@@ -182,8 +179,8 @@ COPY --chown=build:build --from=cargo_minimal_versions /opt/cargo/bin/cargo-mini
 COPY --chown=build:build --from=cargo_check_external_types /opt/cargo/bin/cargo-check-external-types /opt/cargo/bin/cargo-check-external-types
 COPY --chown=build:build --from=maturin /opt/cargo/bin/maturin /opt/cargo/bin/maturin
 COPY --chown=build:build --from=wasm_pack /opt/cargo/bin/wasm-pack /opt/cargo/bin/wasm-pack
-COPY --chown=build:build --from=wasmtime /opt/wasmtime /opt/cargo/bin/wasmtime
-COPY --chown=build:build --from=cargo_wasi /opt/cargo/bin/cargo-wasi /opt/cargo/bin/cargo-wasi
+COPY --chown=build:build --from=wasmtime /opt/cargo/bin/wasmtime /opt/cargo/bin/wasmtime
+COPY --chown=build:build --from=cargo_component /opt/cargo/bin/cargo-component /opt/cargo/bin/cargo-component
 COPY --chown=build:build --from=install_rust /opt/rustup /opt/rustup
 COPY --chown=build:build --from=cargo_semver_checks /opt/cargo/bin/cargo-semver-checks /opt/cargo/bin/cargo-semver-checks
 COPY --chown=build:build --from=cargo_mdbook /opt/cargo/bin/mdbook /opt/cargo/bin/mdbook
diff --git a/tools/ci-cdk/.gitignore b/tools/ci-cdk/.gitignore
index f6764db4c1..135a9d8508 100644
--- a/tools/ci-cdk/.gitignore
+++ b/tools/ci-cdk/.gitignore
@@ -8,3 +8,6 @@ build
 .cdk.staging
 cdk.out
 cdk-outputs.json
+
+# Generated Rust file
+canary-wasm/src/bindings.rs
diff --git a/tools/ci-cdk/README.md b/tools/ci-cdk/README.md
index cbbd304293..34c78d6ea2 100644
--- a/tools/ci-cdk/README.md
+++ b/tools/ci-cdk/README.md
@@ -24,7 +24,7 @@ cd canary-runner
 cargo run -- run --sdk-release-tag <version> --musl --cdk-output ../cdk-outputs.json
 ```
 
-__NOTE:__ You may want to add a `--profile` to the `deploy` command to select a specific credential
+**NOTE:** You may want to add a `--profile` to the deploy command to select a specific credential
 profile to deploy to if you don't want to use the default.
 
 Also, if this is a new test AWS account, be sure it CDK bootstrap it before attempting to deploy.
diff --git a/tools/ci-cdk/canary-lambda/src/canary.rs b/tools/ci-cdk/canary-lambda/src/canary.rs
index 0f3a986a09..6b60811d4e 100644
--- a/tools/ci-cdk/canary-lambda/src/canary.rs
+++ b/tools/ci-cdk/canary-lambda/src/canary.rs
@@ -12,7 +12,7 @@ use aws_config::SdkConfig;
 use tracing::{info_span, Instrument};
 
 use crate::current_canary::paginator_canary;
-use crate::current_canary::{s3_canary, transcribe_canary};
+use crate::current_canary::{s3_canary, transcribe_canary, wasm_canary};
 
 #[macro_export]
 macro_rules! mk_canary {
@@ -35,6 +35,7 @@ pub fn get_canaries_to_run(
         paginator_canary::mk_canary(&sdk_config, &env),
         s3_canary::mk_canary(&sdk_config, &env),
         transcribe_canary::mk_canary(&sdk_config, &env),
+        wasm_canary::mk_canary(&sdk_config, &env),
     ];
 
     canaries
diff --git a/tools/ci-cdk/canary-lambda/src/latest.rs b/tools/ci-cdk/canary-lambda/src/latest.rs
index 238c361166..f034a5578a 100644
--- a/tools/ci-cdk/canary-lambda/src/latest.rs
+++ b/tools/ci-cdk/canary-lambda/src/latest.rs
@@ -6,3 +6,4 @@
 pub(crate) mod paginator_canary;
 pub(crate) mod s3_canary;
 pub(crate) mod transcribe_canary;
+pub(crate) mod wasm_canary;
diff --git a/tools/ci-cdk/canary-lambda/src/latest/wasm_canary.rs b/tools/ci-cdk/canary-lambda/src/latest/wasm_canary.rs
new file mode 100644
index 0000000000..4832a58746
--- /dev/null
+++ b/tools/ci-cdk/canary-lambda/src/latest/wasm_canary.rs
@@ -0,0 +1,172 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+use crate::{mk_canary, CanaryEnv};
+
+use aws_config::SdkConfig;
+use wasmtime::component::{bindgen, Component, Linker};
+use wasmtime::{Engine, Store};
+use wasmtime_wasi::preview2::WasiCtxBuilder;
+
+mk_canary!("wasm", |_sdk_config: &SdkConfig, _env: &CanaryEnv| {
+    wasm_canary()
+});
+
+//This macro creates bindings to call the wasm functions in Rust
+bindgen!({
+    world: "canary-world",
+    path: "../canary-wasm/wit/component.wit",
+    async: true
+});
+
+struct WasiHostCtx {
+    preview2_ctx: wasmtime_wasi::preview2::WasiCtx,
+    preview2_table: wasmtime::component::ResourceTable,
+    wasi_http_ctx: wasmtime_wasi_http::WasiHttpCtx,
+}
+
+impl wasmtime_wasi::preview2::WasiView for WasiHostCtx {
+    fn table(&self) -> &wasmtime::component::ResourceTable {
+        &self.preview2_table
+    }
+
+    fn ctx(&self) -> &wasmtime_wasi::preview2::WasiCtx {
+        &self.preview2_ctx
+    }
+
+    fn table_mut(&mut self) -> &mut wasmtime::component::ResourceTable {
+        &mut self.preview2_table
+    }
+
+    fn ctx_mut(&mut self) -> &mut wasmtime_wasi::preview2::WasiCtx {
+        &mut self.preview2_ctx
+    }
+}
+
+impl wasmtime_wasi_http::types::WasiHttpView for WasiHostCtx {
+    fn ctx(&mut self) -> &mut wasmtime_wasi_http::WasiHttpCtx {
+        &mut self.wasi_http_ctx
+    }
+
+    fn table(&mut self) -> &mut wasmtime::component::ResourceTable {
+        &mut self.preview2_table
+    }
+}
+
+pub async fn wasm_canary() -> anyhow::Result<()> {
+    let wasm_bin_path = std::env::current_dir()
+        .expect("Current dir")
+        .join("aws_sdk_rust_lambda_canary_wasm.wasm");
+
+    // Create a Wasmtime Engine configured to run Components
+    let engine = Engine::new(
+        wasmtime::Config::new()
+            .wasm_component_model(true)
+            .async_support(true),
+    )?;
+
+    // Create our component from the wasm file
+    let component = Component::from_file(&engine, wasm_bin_path)?;
+
+    // Create the linker and link in the necessary WASI bindings
+    let mut linker: Linker<WasiHostCtx> = Linker::new(&engine);
+    link_all_the_things(&mut linker);
+
+    // Configure and create a `WasiCtx`, which WASI functions need access to
+    // through the host state of the store (which in this case is the host state
+    // of the store)
+    let wasi_ctx = WasiCtxBuilder::new()
+        .inherit_stderr()
+        .inherit_stdout()
+        .build();
+
+    let host_ctx = WasiHostCtx {
+        preview2_ctx: wasi_ctx,
+        preview2_table: wasmtime_wasi::preview2::ResourceTable::new(),
+        wasi_http_ctx: wasmtime_wasi_http::WasiHttpCtx {},
+    };
+
+    let mut store: Store<WasiHostCtx> = Store::new(&engine, host_ctx);
+
+    // Instantiate our module with the bindgen! bindings
+    let (bindings, _) = CanaryWorld::instantiate_async(&mut store, &component, &linker).await?;
+
+    let canary_interface = bindings.aws_component_canary_interface();
+    let api_result = canary_interface
+        .call_run_canary(store)
+        .await?
+        .map_err(anyhow::Error::msg)?;
+
+    // Asserting on the post FFI result to confirm everything in the wasm module worked
+    assert!(!api_result.is_empty());
+
+    Ok(())
+}
+
+/// This function adds all of the WASI bindings to the linker
+fn link_all_the_things(linker: &mut Linker<WasiHostCtx>) {
+    //IO
+    wasmtime_wasi::preview2::bindings::io::poll::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Poll");
+    wasmtime_wasi::preview2::bindings::io::error::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Error");
+    wasmtime_wasi::preview2::bindings::io::streams::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Streams");
+
+    //Random
+    wasmtime_wasi::preview2::bindings::random::random::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Random");
+
+    //Clocks
+    wasmtime_wasi::preview2::bindings::wasi::clocks::monotonic_clock::add_to_linker(linker, |cx| {
+        cx
+    })
+    .expect("Failed to link Clock");
+    wasmtime_wasi::preview2::bindings::wasi::clocks::wall_clock::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Wall Clock");
+
+    //Filesystem
+    wasmtime_wasi::preview2::bindings::filesystem::types::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Filesystem Types");
+    wasmtime_wasi::preview2::bindings::filesystem::preopens::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Filesystem Preopen");
+
+    //CLI
+    wasmtime_wasi::preview2::bindings::wasi::cli::environment::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Environment");
+    wasmtime_wasi::preview2::bindings::wasi::cli::exit::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Environment");
+    wasmtime_wasi::preview2::bindings::wasi::cli::stdin::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Stdin");
+    wasmtime_wasi::preview2::bindings::wasi::cli::stdout::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Stdout");
+    wasmtime_wasi::preview2::bindings::wasi::cli::stderr::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Stderr");
+
+    // CLI Terminal
+    wasmtime_wasi::preview2::bindings::wasi::cli::terminal_input::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Terminal Input");
+    wasmtime_wasi::preview2::bindings::wasi::cli::terminal_output::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Terminal Output");
+    wasmtime_wasi::preview2::bindings::wasi::cli::terminal_stdin::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Terminal Stdin");
+    wasmtime_wasi::preview2::bindings::wasi::cli::terminal_stdout::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Terminal Stdout");
+    wasmtime_wasi::preview2::bindings::wasi::cli::terminal_stderr::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link Terminal Stderr");
+
+    //HTTP
+    wasmtime_wasi_http::bindings::http::types::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link HTTP Types");
+    wasmtime_wasi_http::bindings::http::outgoing_handler::add_to_linker(linker, |cx| cx)
+        .expect("Failed to link HTTP Outgoing Handler");
+}
+
+// #[ignore]
+#[cfg(test)]
+#[tokio::test]
+async fn test_wasm_canary() {
+    wasm_canary().await.expect("Wasm return")
+}
diff --git a/tools/ci-cdk/canary-lambda/src/main.rs b/tools/ci-cdk/canary-lambda/src/main.rs
index df0b36c45a..df6a3d5c6a 100644
--- a/tools/ci-cdk/canary-lambda/src/main.rs
+++ b/tools/ci-cdk/canary-lambda/src/main.rs
@@ -123,7 +123,7 @@ async fn lambda_main(sdk_config: SdkConfig) -> Result<Value, Error> {
 }
 
 async fn canary_result(handle: JoinHandle<anyhow::Result<()>>) -> Result<(), String> {
-    match timeout(Duration::from_secs(20), handle).await {
+    match timeout(Duration::from_secs(180), handle).await {
         Err(_timeout) => Err("canary timed out".into()),
         Ok(Ok(result)) => match result {
             Ok(_) => Ok(()),
diff --git a/tools/ci-cdk/canary-runner/src/build_bundle.rs b/tools/ci-cdk/canary-runner/src/build_bundle.rs
index eaea69835e..15ec5c3cbf 100644
--- a/tools/ci-cdk/canary-runner/src/build_bundle.rs
+++ b/tools/ci-cdk/canary-runner/src/build_bundle.rs
@@ -55,6 +55,10 @@ tokio-stream = "0"
 tracing-texray = "0.1.1"
 reqwest = { version = "0.11.14", features = ["rustls-tls"], default-features = false }
 edit-distance = "2"
+wit-bindgen = { version = "0.16.0", features = ["macros", "realloc"] }
+wasmtime = { version = "17.0.1", features = ["component-model"] }
+wasmtime-wasi = "17.0.1"
+wasmtime-wasi-http = "17.0.1"
 "#;
 
 const REQUIRED_SDK_CRATES: &[&str] = &[
@@ -62,6 +66,7 @@ const REQUIRED_SDK_CRATES: &[&str] = &[
     "aws-sdk-s3",
     "aws-sdk-ec2",
     "aws-sdk-transcribestreaming",
+    "aws-smithy-wasm",
 ];
 
 // The elements in this `Vec` should be sorted in an ascending order by the release date.
@@ -258,6 +263,10 @@ pub async fn build_bundle(opt: BuildBundleArgs) -> Result<Option<PathBuf>> {
     let crate_manifest_content = generate_crate_manifest(crate_source)?;
     fs::write(&manifest_path, crate_manifest_content).context("failed to write Cargo.toml")?;
 
+    let wasm_manifest_path = std::env::current_dir()
+        .expect("Current dir")
+        .join("../canary-wasm/Cargo.toml");
+
     if !opt.manifest_only {
         // Compile the canary Lambda
         let mut command = Command::new("cargo");
@@ -271,6 +280,16 @@ pub async fn build_bundle(opt: BuildBundleArgs) -> Result<Option<PathBuf>> {
         }
         handle_failure("cargo build", &command.output()?)?;
 
+        // Compile the wasm canary to a .wasm binary
+        let mut wasm_command = Command::new("cargo");
+        wasm_command
+            .arg("component")
+            .arg("build")
+            .arg("--release")
+            .arg("--manifest-path")
+            .arg(&wasm_manifest_path);
+        handle_failure("cargo component build", &wasm_command.output()?)?;
+
         // Bundle the Lambda
         let repository_root = find_git_repository_root("smithy-rs", canary_path)?;
         let target_path = {
@@ -280,6 +299,14 @@ pub async fn build_bundle(opt: BuildBundleArgs) -> Result<Option<PathBuf>> {
             }
             path.join("release")
         };
+        let wasm_bin_path = {
+            repository_root
+                .join("tools")
+                .join("target")
+                .join("wasm32-wasi")
+                .join("release")
+                .join("aws_sdk_rust_lambda_canary_wasm.wasm")
+        };
         let bin_path = target_path.join("bootstrap");
         let bundle_path = target_path.join(name_bundle(
             &bin_path,
@@ -289,6 +316,7 @@ pub async fn build_bundle(opt: BuildBundleArgs) -> Result<Option<PathBuf>> {
 
         let zip_file = fs::File::create(&bundle_path).context(here!())?;
         let mut zip = zip::ZipWriter::new(zip_file);
+        //Write the canary bin to the zip
         zip.start_file(
             "bootstrap",
             zip::write::FileOptions::default().unix_permissions(0o755),
@@ -296,6 +324,15 @@ pub async fn build_bundle(opt: BuildBundleArgs) -> Result<Option<PathBuf>> {
         .context(here!())?;
         zip.write_all(&fs::read(&bin_path).context(here!("read target"))?)
             .context(here!())?;
+
+        // Write the wasm bin to the zip
+        zip.start_file(
+            "aws_sdk_rust_lambda_canary_wasm.wasm",
+            zip::write::FileOptions::default().unix_permissions(0o644),
+        )
+        .context(here!())?;
+        zip.write_all(&fs::read(wasm_bin_path).context(here!("read wasm bin"))?)
+            .context(here!())?;
         zip.finish().context(here!())?;
 
         println!(
@@ -453,10 +490,15 @@ tokio-stream = "0"
 tracing-texray = "0.1.1"
 reqwest = { version = "0.11.14", features = ["rustls-tls"], default-features = false }
 edit-distance = "2"
+wit-bindgen = { version = "0.16.0", features = ["macros", "realloc"] }
+wasmtime = { version = "17.0.1", features = ["component-model"] }
+wasmtime-wasi = "17.0.1"
+wasmtime-wasi-http = "17.0.1"
 aws-config = { path = "some/sdk/path/aws-config", features = ["behavior-version-latest"] }
 aws-sdk-s3 = { path = "some/sdk/path/s3" }
 aws-sdk-ec2 = { path = "some/sdk/path/ec2" }
 aws-sdk-transcribestreaming = { path = "some/sdk/path/transcribestreaming" }
+aws-smithy-wasm = { path = "some/sdk/path/aws-smithy-wasm" }
 
 [features]
 latest = []
@@ -518,10 +560,15 @@ tokio-stream = "0"
 tracing-texray = "0.1.1"
 reqwest = { version = "0.11.14", features = ["rustls-tls"], default-features = false }
 edit-distance = "2"
+wit-bindgen = { version = "0.16.0", features = ["macros", "realloc"] }
+wasmtime = { version = "17.0.1", features = ["component-model"] }
+wasmtime-wasi = "17.0.1"
+wasmtime-wasi-http = "17.0.1"
 aws-config = { version = "0.46.0", features = ["behavior-version-latest"] }
 aws-sdk-s3 = "0.20.0"
 aws-sdk-ec2 = "0.19.0"
 aws-sdk-transcribestreaming = "0.16.0"
+aws-smithy-wasm = "0.1.0"
 
 [features]
 latest = []
@@ -538,6 +585,7 @@ default = ["latest"]
                         crate_version("aws-sdk-s3", "0.20.0"),
                         crate_version("aws-sdk-ec2", "0.19.0"),
                         crate_version("aws-sdk-transcribestreaming", "0.16.0"),
+                        crate_version("aws-smithy-wasm", "0.1.0"),
                     ]
                     .into_iter()
                     .collect(),
diff --git a/tools/ci-cdk/canary-runner/src/run.rs b/tools/ci-cdk/canary-runner/src/run.rs
index 8fd8cb4064..6d6d4e9f63 100644
--- a/tools/ci-cdk/canary-runner/src/run.rs
+++ b/tools/ci-cdk/canary-runner/src/run.rs
@@ -388,7 +388,7 @@ async fn create_lambda_fn(
         )
         .publish(true)
         .environment(env_builder.build())
-        .timeout(60)
+        .timeout(180)
         .send()
         .await
         .context(here!("failed to create canary Lambda function"))?;
diff --git a/tools/ci-cdk/canary-wasm/Cargo.lock b/tools/ci-cdk/canary-wasm/Cargo.lock
new file mode 100644
index 0000000000..112f72a1dc
--- /dev/null
+++ b/tools/ci-cdk/canary-wasm/Cargo.lock
@@ -0,0 +1,1286 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "anyhow"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "aws-config"
+version = "1.1.7"
+dependencies = [
+ "aws-credential-types",
+ "aws-runtime",
+ "aws-sdk-sts",
+ "aws-smithy-async",
+ "aws-smithy-http",
+ "aws-smithy-json",
+ "aws-smithy-runtime",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "aws-types",
+ "bytes",
+ "fastrand",
+ "http 0.2.11",
+ "hyper",
+ "time",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "aws-credential-types"
+version = "1.1.7"
+dependencies = [
+ "aws-smithy-async",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "zeroize",
+]
+
+[[package]]
+name = "aws-runtime"
+version = "1.1.7"
+dependencies = [
+ "aws-credential-types",
+ "aws-sigv4",
+ "aws-smithy-async",
+ "aws-smithy-eventstream",
+ "aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "aws-types",
+ "bytes",
+ "fastrand",
+ "http 0.2.11",
+ "http-body",
+ "percent-encoding",
+ "pin-project-lite",
+ "tracing",
+ "uuid",
+]
+
+[[package]]
+name = "aws-sdk-rust-lambda-canary-wasm"
+version = "0.1.0"
+dependencies = [
+ "aws-config",
+ "aws-sdk-s3",
+ "aws-smithy-async",
+ "aws-smithy-wasm",
+ "tokio",
+ "wit-bindgen",
+]
+
+[[package]]
+name = "aws-sdk-s3"
+version = "0.0.0-local"
+dependencies = [
+ "aws-credential-types",
+ "aws-runtime",
+ "aws-sigv4",
+ "aws-smithy-async",
+ "aws-smithy-checksums",
+ "aws-smithy-eventstream",
+ "aws-smithy-http",
+ "aws-smithy-json",
+ "aws-smithy-runtime",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "aws-smithy-xml",
+ "aws-types",
+ "bytes",
+ "http 0.2.11",
+ "http-body",
+ "once_cell",
+ "percent-encoding",
+ "regex-lite",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "aws-sdk-sts"
+version = "0.0.0-local"
+dependencies = [
+ "aws-credential-types",
+ "aws-runtime",
+ "aws-smithy-async",
+ "aws-smithy-http",
+ "aws-smithy-json",
+ "aws-smithy-query",
+ "aws-smithy-runtime",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "aws-smithy-xml",
+ "aws-types",
+ "http 0.2.11",
+ "once_cell",
+ "regex-lite",
+ "tracing",
+]
+
+[[package]]
+name = "aws-sigv4"
+version = "1.1.7"
+dependencies = [
+ "aws-credential-types",
+ "aws-smithy-eventstream",
+ "aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "bytes",
+ "form_urlencoded",
+ "hex",
+ "hmac",
+ "http 0.2.11",
+ "http 1.0.0",
+ "once_cell",
+ "percent-encoding",
+ "sha2",
+ "time",
+ "tracing",
+]
+
+[[package]]
+name = "aws-smithy-async"
+version = "1.1.7"
+dependencies = [
+ "futures-util",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "aws-smithy-checksums"
+version = "0.60.6"
+dependencies = [
+ "aws-smithy-http",
+ "aws-smithy-types",
+ "bytes",
+ "crc32c",
+ "crc32fast",
+ "hex",
+ "http 0.2.11",
+ "http-body",
+ "md-5",
+ "pin-project-lite",
+ "sha1",
+ "sha2",
+ "tracing",
+]
+
+[[package]]
+name = "aws-smithy-eventstream"
+version = "0.60.4"
+dependencies = [
+ "aws-smithy-types",
+ "bytes",
+ "crc32fast",
+]
+
+[[package]]
+name = "aws-smithy-http"
+version = "0.60.6"
+dependencies = [
+ "aws-smithy-eventstream",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "bytes",
+ "bytes-utils",
+ "futures-core",
+ "http 0.2.11",
+ "http-body",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "pin-utils",
+ "tracing",
+]
+
+[[package]]
+name = "aws-smithy-json"
+version = "0.60.6"
+dependencies = [
+ "aws-smithy-types",
+]
+
+[[package]]
+name = "aws-smithy-query"
+version = "0.60.6"
+dependencies = [
+ "aws-smithy-types",
+ "urlencoding",
+]
+
+[[package]]
+name = "aws-smithy-runtime"
+version = "1.1.7"
+dependencies = [
+ "aws-smithy-async",
+ "aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "bytes",
+ "fastrand",
+ "http 0.2.11",
+ "http-body",
+ "once_cell",
+ "pin-project-lite",
+ "pin-utils",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "aws-smithy-runtime-api"
+version = "1.1.7"
+dependencies = [
+ "aws-smithy-async",
+ "aws-smithy-types",
+ "bytes",
+ "http 0.2.11",
+ "http 1.0.0",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "aws-smithy-types"
+version = "1.1.7"
+dependencies = [
+ "base64-simd",
+ "bytes",
+ "bytes-utils",
+ "futures-core",
+ "http 0.2.11",
+ "http-body",
+ "itoa",
+ "num-integer",
+ "pin-project-lite",
+ "pin-utils",
+ "ryu",
+ "serde",
+ "time",
+]
+
+[[package]]
+name = "aws-smithy-wasm"
+version = "0.1.0"
+dependencies = [
+ "aws-smithy-async",
+ "aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "bytes",
+ "http 1.0.0",
+ "tokio",
+ "tower",
+ "tracing",
+ "wasi",
+]
+
+[[package]]
+name = "aws-smithy-xml"
+version = "0.60.6"
+dependencies = [
+ "xmlparser",
+]
+
+[[package]]
+name = "aws-types"
+version = "1.1.7"
+dependencies = [
+ "aws-credential-types",
+ "aws-smithy-async",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "http 0.2.11",
+ "rustc_version",
+ "tracing",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base64-simd"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195"
+dependencies = [
+ "outref",
+ "vsimd",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "bytes"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+
+[[package]]
+name = "bytes-utils"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35"
+dependencies = [
+ "bytes",
+ "either",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32c"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2"
+dependencies = [
+ "rustc_version",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "either"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "fastrand"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+
+[[package]]
+name = "futures-task"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+
+[[package]]
+name = "futures-util"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "http"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http 0.2.11",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "0.14.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "http 0.2.11",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "id-arena"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+ "serde",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
+name = "leb128"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
+
+[[package]]
+name = "libc"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "log"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+
+[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "object"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "outref"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.78"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex-lite"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
+[[package]]
+name = "semver"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
+
+[[package]]
+name = "serde"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.196"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.113"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+
+[[package]]
+name = "spdx"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62bde1398b09b9f93fc2fc9b9da86e362693e999d3a54a8ac47a99a5a73f638b"
+dependencies = [
+ "smallvec",
+]
+
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
+[[package]]
+name = "syn"
+version = "2.0.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "time"
+version = "0.3.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
+dependencies = [
+ "deranged",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.36.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
+dependencies = [
+ "backtrace",
+ "pin-project-lite",
+ "tokio-macros",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "urlencoding"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+
+[[package]]
+name = "uuid"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "vsimd"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.12.0+wasi-0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "457dd7e321b36e7d9d275997825e17ff9dcba2f6c8c0ff656e2f46db6c8579ef"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasm-encoder"
+version = "0.38.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f"
+dependencies = [
+ "leb128",
+]
+
+[[package]]
+name = "wasm-encoder"
+version = "0.41.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "972f97a5d8318f908dded23594188a90bcd09365986b1163e66d70170e5287ae"
+dependencies = [
+ "leb128",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.10.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18ebaa7bd0f9e7a5e5dd29b9a998acf21c4abed74265524dd7e85934597bfb10"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "spdx",
+ "wasm-encoder 0.41.2",
+ "wasmparser 0.121.2",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.118.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c"
+dependencies = [
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.121.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab"
+dependencies = [
+ "bitflags",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b76f1d099678b4f69402a421e888bbe71bf20320c2f3f3565d0e7484dbe5bc20"
+dependencies = [
+ "bitflags",
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75d55e1a488af2981fb0edac80d8d20a51ac36897a1bdef4abde33c29c1b6d0d"
+dependencies = [
+ "anyhow",
+ "wit-component",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a01ff9cae7bf5736750d94d91eb8a49f5e3a04aff1d1a3218287d9b2964510f8"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804a98e2538393d47aa7da65a7348116d6ff403b426665152b70a168c0146d49"
+dependencies = [
+ "anyhow",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.18.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b8a35a2a9992898c9d27f1664001860595a4bc99d32dd3599d547412e17d7e2"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder 0.38.1",
+ "wasm-metadata",
+ "wasmparser 0.118.2",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+]
+
+[[package]]
+name = "xmlparser"
+version = "0.13.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
+
+[[package]]
+name = "zeroize"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
diff --git a/tools/ci-cdk/canary-wasm/Cargo.toml b/tools/ci-cdk/canary-wasm/Cargo.toml
new file mode 100644
index 0000000000..de883a420c
--- /dev/null
+++ b/tools/ci-cdk/canary-wasm/Cargo.toml
@@ -0,0 +1,25 @@
+
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# IMPORTANT: Don't edit this file directly! Run `canary-runner build-bundle` to modify this file instead.
+[package]
+name = "aws-sdk-rust-lambda-canary-wasm"
+version = "0.1.0"
+edition = "2021"
+license = "Apache-2.0"
+
+[dependencies]
+tokio = { version = "1.36.0", features = ["macros", "rt", "time"] }
+wit-bindgen = { version = "0.16.0", features = ["macros", "realloc"] }
+aws-config = { path = "../../../aws/sdk/build/aws-sdk/sdk/aws-config", default-features = false, features = ["behavior-version-latest"] }
+aws-sdk-s3 = { path = "../../../aws/sdk/build/aws-sdk/sdk/s3", default-features = false }
+aws-smithy-wasm = { path = "../../../aws/sdk/build/aws-sdk/sdk/aws-smithy-wasm" }
+aws-smithy-async = { path = "../../../aws/sdk/build/aws-sdk/sdk/aws-smithy-async", default-features = false, features = ["rt-tokio"]}
+
+[lib]
+crate-type = ["cdylib"]
+
+# metadata used by cargo-component to identify which wit world to embed in the binary
+[package.metadata.component]
+package = "aws:component"
diff --git a/tools/ci-cdk/canary-wasm/src/lib.rs b/tools/ci-cdk/canary-wasm/src/lib.rs
new file mode 100644
index 0000000000..6d90399ec0
--- /dev/null
+++ b/tools/ci-cdk/canary-wasm/src/lib.rs
@@ -0,0 +1,63 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+use aws_config::Region;
+use aws_sdk_s3 as s3;
+use aws_smithy_async::rt::sleep::TokioSleep;
+use aws_smithy_wasm::wasi::WasiHttpClientBuilder;
+
+//Generates the Rust bindings from the wit file
+wit_bindgen::generate!({
+    world: "canary-world",
+    exports: {
+        "aws:component/canary-interface": Component
+    }
+});
+
+struct Component;
+
+impl exports::aws::component::canary_interface::Guest for Component {
+    fn run_canary() -> Result<Vec<String>, String> {
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_time()
+            .build()
+            .expect("Failed to generate runtime");
+        let res = rt.block_on(run_canary())?;
+        Ok(res)
+    }
+}
+
+async fn run_canary() -> Result<Vec<String>, String> {
+    let http_client = WasiHttpClientBuilder::new().build();
+    let sleep = TokioSleep::new();
+    let config = aws_config::from_env()
+        .region(Region::new("us-east-2"))
+        .no_credentials()
+        .http_client(http_client)
+        .sleep_impl(sleep)
+        .load()
+        .await;
+
+    let client = s3::Client::new(&config);
+    let result = client
+        .list_objects_v2()
+        .bucket("nara-national-archives-catalog")
+        .delimiter("/")
+        .prefix("authority-records/organization/")
+        .max_keys(5)
+        .send()
+        .await
+        .expect("Failed to ListObjects");
+
+    //For ease of modeling the return we just extract the keys from the objects
+    let object_names: Vec<String> = result
+        .contents
+        .expect("No S3 Objects")
+        .iter()
+        .map(|obj| obj.key().expect("Object has no name").to_string())
+        .collect();
+
+    Ok(object_names)
+}
diff --git a/tools/ci-cdk/canary-wasm/wit/component.wit b/tools/ci-cdk/canary-wasm/wit/component.wit
new file mode 100644
index 0000000000..a23ee0aadf
--- /dev/null
+++ b/tools/ci-cdk/canary-wasm/wit/component.wit
@@ -0,0 +1,15 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package aws:component;
+ 
+interface canary-interface {
+    run-canary: func() -> result<list<string>, string>;
+}
+ 
+world canary-world {
+    export canary-interface;
+}
+     
\ No newline at end of file
diff --git a/tools/ci-scripts/check-aws-config b/tools/ci-scripts/check-aws-config
index 135ab38eb1..49f1439027 100755
--- a/tools/ci-scripts/check-aws-config
+++ b/tools/ci-scripts/check-aws-config
@@ -55,6 +55,6 @@ cargo check --target wasm32-wasi --no-default-features
 # TODO(https://github.com/smithy-lang/smithy-rs/issues/2499): Uncomment the following once aws-config tests compile for WASM
 # echo "${C_YELLOW}## Testing the wasm32-unknown-unknown and wasm32-wasi targets${C_RESET}"
 # wasm-pack test --node -- --no-default-features
-# cargo wasi test --no-default-features
+# cargo test --target wasm32-wasi --no-default-features
 
 popd &>/dev/null
diff --git a/tools/ci-scripts/check-aws-sdk-standalone-integration-tests b/tools/ci-scripts/check-aws-sdk-standalone-integration-tests
index c331f9997b..9ba41631dc 100755
--- a/tools/ci-scripts/check-aws-sdk-standalone-integration-tests
+++ b/tools/ci-scripts/check-aws-sdk-standalone-integration-tests
@@ -39,4 +39,10 @@ find "${tmp_dir}"
 
 pushd "${tmp_dir}/aws/sdk/integration-tests"
 cargo check --tests --all-features
+
+# Running WebAssembly (WASI) specific integration tests
+pushd "${tmp_dir}/aws/sdk/integration-tests/webassembly" &>/dev/null
+cargo check --tests --all-features
+
+popd
 popd