diff --git a/Cargo.lock b/Cargo.lock index 0888d3b..50befcc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -652,7 +652,7 @@ dependencies = [ [[package]] name = "composable-http-server" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -660,16 +660,20 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", "serde", "serde_json", "tokio", "tracing", "tracing-subscriber", + "uuid", ] [[package]] name = "composable-interceptor" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -682,9 +686,26 @@ dependencies = [ "wit-parser 0.245.1", ] +[[package]] +name = "composable-otel" +version = "0.5.0-alpha.2" +dependencies = [ + "anyhow", + "composable-runtime", + "indexmap 2.13.0", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "serde", + "serde_json", + "tokio", + "tracing", + "wasmtime", +] + [[package]] name = "composable-runtime" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -1626,6 +1647,17 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.32" @@ -2006,6 +2038,19 @@ dependencies = [ "webpki-roots 1.0.6", ] +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.20" @@ -2890,6 +2935,81 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "opentelemetry" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry", + "reqwest 0.12.28", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +dependencies = [ + "http", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost 0.14.3", + "reqwest 0.12.28", + "thiserror 2.0.18", + "tokio", + "tonic", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost 0.14.3", + "tonic", + "tonic-prost", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand 0.9.2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -2990,7 +3110,7 @@ checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" dependencies = [ "heck 0.4.1", "itertools 0.11.0", - "prost", + "prost 0.12.6", "prost-types", ] @@ -3004,7 +3124,7 @@ dependencies = [ "chrono", "pbjson", "pbjson-build", - "prost", + "prost 0.12.6", "prost-build", "serde", ] @@ -3089,6 +3209,26 @@ dependencies = [ "serde", ] +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -3244,7 +3384,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", ] [[package]] @@ -3261,7 +3411,7 @@ dependencies = [ "once_cell", "petgraph 0.6.5", "prettyplease", - "prost", + "prost 0.12.6", "prost-types", "regex", "syn", @@ -3281,6 +3431,19 @@ dependencies = [ "syn", ] +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "prost-reflect" version = "0.13.1" @@ -3290,7 +3453,7 @@ dependencies = [ "logos", "miette", "once_cell", - "prost", + "prost 0.12.6", "prost-types", ] @@ -3300,7 +3463,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost", + "prost 0.12.6", ] [[package]] @@ -3311,7 +3474,7 @@ checksum = "ac532509cee918d40f38c3e12f8ef9230f215f017d54de7dd975015538a42ce7" dependencies = [ "bytes", "miette", - "prost", + "prost 0.12.6", "prost-reflect", "prost-types", "protox-parse", @@ -4677,6 +4840,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -4806,6 +4980,43 @@ version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +[[package]] +name = "tonic" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + [[package]] name = "topological-sort" version = "0.2.2" @@ -4820,11 +5031,15 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", + "indexmap 2.13.0", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -5224,7 +5439,7 @@ dependencies = [ "pbjson", "pbjson-build", "pbjson-types", - "prost", + "prost 0.12.6", "prost-build", "prost-types", "protox", @@ -5244,7 +5459,7 @@ dependencies = [ "hex", "indexmap 2.13.0", "pbjson-types", - "prost", + "prost 0.12.6", "prost-types", "semver", "serde", @@ -5264,7 +5479,7 @@ checksum = "8b8d8110b6800c43422676201a6a62167769b015ca29a8fcab67d789ac8b9c63" dependencies = [ "anyhow", "indexmap 2.13.0", - "prost", + "prost 0.12.6", "thiserror 1.0.69", "warg-crypto", "warg-protobuf", diff --git a/Cargo.toml b/Cargo.toml index 65ba522..ae3adc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,10 @@ categories = ["wasm"] keywords = ["wasm"] [workspace] -members = [".", "crates/http-server", "crates/interceptor"] +members = [".", "crates/http-server", "crates/interceptor", "crates/opentelemetry"] [workspace.package] -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" license = "Apache-2.0" repository = "https://github.com/modulewise/composable-runtime" edition = "2024" @@ -23,21 +23,26 @@ anyhow = "1" clap = { version = "4.6", features = ["derive"] } http-body-util = "0.1" hyper = { version = "1", features = ["http1", "http2"] } -hyper-util = { version = "0.1", features = ["tokio"] } +hyper-util = { version = "0.1", features = ["server-graceful", "tokio"] } +opentelemetry = "0.31" +opentelemetry-otlp = { version = "0.31", default-features = false } +opentelemetry_sdk = "0.31" serde = { version = "1.0", features = ["derive"] } serde_json = "1" tempfile = "3" tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time"] } tracing = "0.1" +uuid = { version = "1", features = ["v4"] } wasm-encoder = "0.245" wasmparser = "0.245" +wasmtime = "42" wat = "1.245" wit-parser = "0.245" [dependencies] anyhow.workspace = true clap.workspace = true -composable-interceptor = { version = "0.5.0-alpha.1", path = "crates/interceptor" } +composable-interceptor = { version = "0.5.0-alpha.2", path = "crates/interceptor" } http-body-util.workspace = true hyper = { workspace = true, features = ["client", "http1", "http2"] } oci-client = "0.16" @@ -51,11 +56,11 @@ tokio-util = { version = "0.7", optional = true } toml = "1" tracing.workspace = true tracing-subscriber = { version = "0.3", features = ["env-filter"] } -uuid = { version = "1", features = ["v4"] } +uuid.workspace = true wac-graph = "0.9" wac-types = "0.9" wasm-pkg-client = "0.15" -wasmtime = "42" +wasmtime = { workspace = true } wasmtime-wasi = "42" wasmtime-wasi-config = "42" wasmtime-wasi-http = "42" diff --git a/README.md b/README.md index 60306a8..d9e2a9e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,8 @@ That incrementally introduces each concept along the way: - [http-server](examples/http-server): The greeter component invoked by the runtime when HTTP requests arrive, either directly or via a messaging channel depending on the route - [interceptor](examples/interceptor): An interceptor component, dynamically generated from generic advice, logs before and after greeter function calls - [messsaging](examples/messaging): The greeter component invoked when messages arrive via `composable publish` -- [otel](examples/otel): A guest component uses wasi:otel backed by either a host-capability or an adapter component +- [otel-components](examples/otel-components): A guest component uses wasi:otel backed by either a host-capability or an adapter component +- [otel-service](examples/otel-service): Trace propagation using the OtelService and HttpService sub-crates - [service](examples/service): A custom Service provides a ConfigHandler, HostCapability, and its own lifecycle This project also provides a foundation for the diff --git a/crates/http-server/Cargo.toml b/crates/http-server/Cargo.toml index 723adf1..1311744 100644 --- a/crates/http-server/Cargo.toml +++ b/crates/http-server/Cargo.toml @@ -12,15 +12,19 @@ keywords = ["wasm"] [dependencies] anyhow.workspace = true clap = { workspace = true, optional = true } -composable-runtime = { version = "0.5.0-alpha.1", path = "../..", features = ["messaging"] } +composable-runtime = { version = "0.5.0-alpha.2", path = "../..", features = ["messaging"] } http-body-util.workspace = true hyper = { workspace = true, features = ["server", "http1"] } hyper-util.workspace = true +opentelemetry.workspace = true +opentelemetry_sdk = { workspace = true, features = ["rt-tokio", "experimental_trace_batch_span_processor_with_async_runtime", "trace"] } +opentelemetry-otlp = { workspace = true, features = ["grpc-tonic", "http-proto", "reqwest-client", "trace"] } serde.workspace = true serde_json.workspace = true tokio.workspace = true tracing.workspace = true tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true } +uuid = { workspace = true } [features] default = ["cli"] diff --git a/crates/http-server/src/config.rs b/crates/http-server/src/config.rs index 7cfb068..ecea9b4 100644 --- a/crates/http-server/src/config.rs +++ b/crates/http-server/src/config.rs @@ -35,6 +35,10 @@ pub struct ServerConfig { pub name: String, pub port: u16, pub routes: Vec, + /// OTLP endpoint for host-side span export. If absent, no host spans are exported. + pub otlp_endpoint: Option, + /// OTLP protocol: "grpc" (default) or "http/protobuf". + pub otlp_protocol: String, } pub type SharedConfig = Arc>>; @@ -68,7 +72,10 @@ impl ConfigHandler for HttpServerConfigHandler { } fn claimed_properties(&self) -> HashMap<&str, &[&str]> { - HashMap::from([("server", ["type", "port", "route"].as_slice())]) + HashMap::from([( + "server", + ["type", "port", "route", "otlp-endpoint", "otlp-protocol"].as_slice(), + )]) } fn handle_category( @@ -105,6 +112,26 @@ impl ConfigHandler for HttpServerConfigHandler { } }; + let otlp_endpoint = match properties.remove("otlp-endpoint") { + Some(serde_json::Value::String(s)) => Some(s), + Some(got) => { + return Err(anyhow::anyhow!( + "Server '{name}': 'otlp-endpoint' must be a string, got {got}" + )); + } + None => None, + }; + + let otlp_protocol = match properties.remove("otlp-protocol") { + Some(serde_json::Value::String(s)) => s, + Some(got) => { + return Err(anyhow::anyhow!( + "Server '{name}': 'otlp-protocol' must be a string, got {got}" + )); + } + None => "grpc".to_string(), + }; + let routes = parse_routes(name, &mut properties)?; if !properties.is_empty() { @@ -118,6 +145,8 @@ impl ConfigHandler for HttpServerConfigHandler { name: name.to_string(), port, routes, + otlp_endpoint, + otlp_protocol, }); Ok(()) } diff --git a/crates/http-server/src/server.rs b/crates/http-server/src/server.rs index 3ae1257..3f849cb 100644 --- a/crates/http-server/src/server.rs +++ b/crates/http-server/src/server.rs @@ -8,12 +8,19 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::{Method, Request, Response, StatusCode}; use hyper_util::rt::TokioIo; +use hyper_util::server::graceful::GracefulShutdown; +use opentelemetry::trace::{Span, SpanKind, Tracer, TracerProvider}; +use opentelemetry_otlp::{SpanExporter, WithExportConfig}; +use opentelemetry_sdk::{ + runtime::Tokio, + trace::{SdkTracerProvider, span_processor_with_async_runtime::BatchSpanProcessor}, +}; use tokio::net::TcpListener; use tokio::sync::watch; -use composable_runtime::{ComponentInvoker, MessagePublisher}; +use composable_runtime::{ComponentInvoker, MessagePublisher, PROPAGATED_HEADERS}; -use crate::config::{RouteConfig, RouteTarget}; +use crate::config::{RouteConfig, RouteTarget, ServerConfig}; struct Route { name: String, @@ -124,6 +131,7 @@ struct Router { routes: Vec, invoker: Arc, publisher: Option>, + tracer_provider: Option, } impl Router { @@ -171,29 +179,98 @@ impl Router { params: HashMap, req: Request, ) -> Response> { - let component = match self.invoker.get_component(component_name) { - Some(c) => c, - None => { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Full::new(Bytes::from(format!( - "component '{component_name}' not found" - )))) - .unwrap(); + // Extract propagated headers from the inbound request. + let mut context: HashMap = HashMap::new(); + for key in PROPAGATED_HEADERS { + if let Some(val) = req.headers().get(*key).and_then(|v| v.to_str().ok()) { + context.insert(key.to_string(), val.to_string()); } + } + + let mut host_span = self.tracer_provider.as_ref().map(|tp| { + use opentelemetry::propagation::TextMapPropagator; + use opentelemetry_sdk::propagation::TraceContextPropagator; + let propagator = TraceContextPropagator::new(); + let parent_cx = propagator.extract(&context); + let tracer = tp.tracer("composable-http-server"); + tracer + .span_builder(format!("{component_name}/{function_name}")) + .with_kind(SpanKind::Server) + .start_with_context(&tracer, &parent_cx) + }); + + // Update traceparent with the host span if newly created, + // or generate one if not already provided by inbound request. + if let Some(span) = &host_span { + let sc = span.span_context(); + context.insert( + "traceparent".to_string(), + format!( + "00-{:032x}-{:016x}-{:02x}", + sc.trace_id(), + sc.span_id(), + sc.trace_flags() + ), + ); + } else if !context.contains_key("traceparent") { + let trace_id = uuid::Uuid::new_v4().as_simple().to_string(); + let span_id = &uuid::Uuid::new_v4().as_simple().to_string()[..16]; + context.insert( + "traceparent".to_string(), + format!("00-{trace_id}-{span_id}-01"), + ); }; - let function = match component.functions.get(function_name) { - Some(f) => f, - None => { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Full::new(Bytes::from(format!( - "function '{function_name}' not found on '{component_name}'" - )))) - .unwrap(); + let result = self + .invoke_inner( + component_name, + function_name, + body_param, + params, + req, + context, + ) + .await; + + if let Some(span) = &mut host_span { + match &result { + Ok(_) => span.set_status(opentelemetry::trace::Status::Ok), + Err((_, msg)) => span.set_status(opentelemetry::trace::Status::error(msg.clone())), } - }; + span.end(); + } + + match result { + Ok(response) => response, + Err((status, msg)) => Response::builder() + .status(status) + .body(Full::new(Bytes::from(msg))) + .unwrap(), + } + } + + async fn invoke_inner( + &self, + component_name: &str, + function_name: &str, + body_param: Option<&str>, + params: HashMap, + req: Request, + context: HashMap, + ) -> Result>, (StatusCode, String)> { + let component = self.invoker.get_component(component_name).ok_or_else(|| { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("component '{component_name}' not found"), + ) + })?; + + let function = component.functions.get(function_name).ok_or_else(|| { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("function '{function_name}' not found on '{component_name}'"), + ) + })?; let body_value = if body_param.is_some() { let content_type = req @@ -203,52 +280,35 @@ impl Router { .unwrap_or("application/json") .to_string(); - let body_bytes = match req.collect().await { - Ok(collected) => collected.to_bytes(), - Err(e) => { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Full::new(Bytes::from(format!("failed to read body: {e}")))) - .unwrap(); - } - }; + let body_bytes = req + .collect() + .await + .map_err(|e| (StatusCode::BAD_REQUEST, format!("failed to read body: {e}")))? + .to_bytes(); let value = if content_type.starts_with("text/plain") { - match std::str::from_utf8(&body_bytes) { - Ok(text) => serde_json::Value::String(text.to_string()), - Err(e) => { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Full::new(Bytes::from(format!( - "body is not valid UTF-8: {e}" - )))) - .unwrap(); - } - } + std::str::from_utf8(&body_bytes) + .map(|text| serde_json::Value::String(text.to_string())) + .map_err(|e| { + ( + StatusCode::BAD_REQUEST, + format!("body is not valid UTF-8: {e}"), + ) + })? } else if content_type.starts_with("application/json") { - match serde_json::from_slice::(&body_bytes) { - Ok(value) => value, - Err(e) => { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Full::new(Bytes::from(format!("invalid JSON body: {e}")))) - .unwrap(); - } - } + serde_json::from_slice::(&body_bytes) + .map_err(|e| (StatusCode::BAD_REQUEST, format!("invalid JSON body: {e}")))? } else { - return Response::builder() - .status(StatusCode::UNSUPPORTED_MEDIA_TYPE) - .body(Full::new(Bytes::from(format!( - "unsupported content type: {content_type}" - )))) - .unwrap(); + return Err(( + StatusCode::UNSUPPORTED_MEDIA_TYPE, + format!("unsupported content type: {content_type}"), + )); }; Some(value) } else { None }; - // Build args: path params by name, body param if configured let mut args: Vec = Vec::new(); for param in function.params() { if let Some(value) = params.get(param.name.as_str()) { @@ -256,34 +316,30 @@ impl Router { } else if body_param == Some(param.name.as_str()) { args.push(body_value.clone().unwrap()); } else { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Full::new(Bytes::from(format!( - "missing parameter '{}'", - param.name.as_str() - )))) - .unwrap(); + return Err(( + StatusCode::BAD_REQUEST, + format!("missing parameter '{}'", param.name.as_str()), + )); } } - match self + let invoke_result = self .invoker - .invoke(component_name, function_name, args) + .invoke(component_name, function_name, args, Some(context), None) .await - { - Ok(result) => { - let body = serde_json::to_vec(&result).unwrap_or_default(); - Response::builder() - .status(StatusCode::OK) - .header("content-type", "application/json") - .body(Full::new(Bytes::from(body))) - .unwrap() - } - Err(e) => Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Full::new(Bytes::from(format!("invocation error: {e}")))) - .unwrap(), - } + .map_err(|e| { + ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("invocation error: {e}"), + ) + })?; + + let body = serde_json::to_vec(&invoke_result).unwrap_or_default(); + Ok(Response::builder() + .status(StatusCode::OK) + .header("content-type", "application/json") + .body(Full::new(Bytes::from(body))) + .unwrap()) } async fn publish_to_channel( @@ -338,51 +394,138 @@ impl Router { } } -/// Start an HTTP server on the given port with the given routes. -/// Returns when the shutdown signal is received. -pub async fn run( +pub struct HttpServer { port: u16, - routes: Vec, - invoker: Arc, - publisher: Option>, - mut shutdown: watch::Receiver, -) -> Result<()> { - let routes: Vec = routes - .iter() - .map(Route::from_config) - .collect::>()?; - - let router = Arc::new(Router { - routes, - invoker, - publisher, - }); - - let listener = TcpListener::bind(("0.0.0.0", port)).await?; - tracing::info!(port, "HTTP server listening"); - - loop { - tokio::select! { - accept = listener.accept() => { - let (stream, _addr) = accept?; - let router = Arc::clone(&router); - tokio::spawn(async move { - let io = TokioIo::new(stream); - let service = service_fn(move |req| { - let router = Arc::clone(&router); - async move { router.handle(req).await } + router: Arc, + tracer_provider: Option, +} + +impl HttpServer { + pub fn new( + config: ServerConfig, + invoker: Arc, + publisher: Option>, + ) -> Result { + let routes: Vec = config + .routes + .iter() + .map(Route::from_config) + .collect::>()?; + + let tracer_provider = if let Some(endpoint) = &config.otlp_endpoint { + match build_tracer_provider(endpoint, &config.otlp_protocol, &config.name) { + Ok(tp) => Some(tp), + Err(e) => { + tracing::warn!(server = %config.name, "failed to build OTLP span exporter: {e}"); + None + } + } + } else { + None + }; + + let router = Arc::new(Router { + routes, + invoker, + publisher, + tracer_provider: tracer_provider.clone(), + }); + + Ok(Self { + port: config.port, + router, + tracer_provider, + }) + } + + pub async fn run(self, mut shutdown: watch::Receiver) -> Result<()> { + let HttpServer { + port, + router, + tracer_provider, + } = self; + + let listener = TcpListener::bind(("0.0.0.0", port)).await?; + tracing::info!(port, "HTTP server listening"); + + let graceful = GracefulShutdown::new(); + + loop { + tokio::select! { + accept = listener.accept() => { + let (stream, _addr) = accept?; + let router = Arc::clone(&router); + let conn = http1::Builder::new().serve_connection( + TokioIo::new(stream), + service_fn(move |req| { + let router = Arc::clone(&router); + async move { router.handle(req).await } + }), + ); + let conn = graceful.watch(conn); + tokio::spawn(async move { + if let Err(e) = conn.await { + tracing::error!("connection error: {e}"); + } }); - if let Err(e) = http1::Builder::new().serve_connection(io, service).await { - tracing::error!("connection error: {e}"); - } - }); + } + _ = shutdown.changed() => { + tracing::info!(port, "HTTP server shutting down"); + break; + } } - _ = shutdown.changed() => { - tracing::info!(port, "HTTP server shutting down"); - break; + } + + tokio::select! { + _ = graceful.shutdown() => {} + _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => { + tracing::warn!(port, "timed out waiting for connections to close"); } } + + // Drop router (and its provider clone) before shutting down the provider. + drop(router); + + // spawn_blocking since BatchSpanProcessor::shutdown() calls block_on internally. + if let Some(provider) = tracer_provider { + let _ = tokio::task::spawn_blocking(move || provider.shutdown()).await; + } + + Ok(()) } +} - Ok(()) +fn build_tracer_provider( + endpoint: &str, + protocol: &str, + service_name: &str, +) -> Result { + let exporter = match protocol { + "http/protobuf" => SpanExporter::builder() + .with_http() + .with_endpoint(endpoint) + .build() + .map_err(|e| anyhow::anyhow!("failed to build span exporter: {e}"))?, + _ => { + if protocol != "grpc" { + tracing::warn!(protocol, "unrecognized OTLP protocol, defaulting to grpc"); + } + SpanExporter::builder() + .with_tonic() + .with_endpoint(endpoint) + .build() + .map_err(|e| anyhow::anyhow!("failed to build span exporter: {e}"))? + } + }; + let resource = opentelemetry_sdk::Resource::builder() + .with_attribute(opentelemetry::KeyValue::new( + "service.name", + service_name.to_string(), + )) + .build(); + let processor = BatchSpanProcessor::builder(exporter, Tokio).build(); + Ok(SdkTracerProvider::builder() + .with_resource(resource) + .with_span_processor(processor) + .build()) } diff --git a/crates/http-server/src/service.rs b/crates/http-server/src/service.rs index 6122cca..e8ad02d 100644 --- a/crates/http-server/src/service.rs +++ b/crates/http-server/src/service.rs @@ -9,6 +9,7 @@ use tokio::task::JoinHandle; use composable_runtime::{ComponentInvoker, ConfigHandler, MessagePublisher, Service}; use crate::config::{self, HttpServerConfigHandler, ServerConfig, SharedConfig}; +use crate::server::HttpServer; /// HTTP Server support for the composable runtime. /// @@ -72,19 +73,16 @@ impl Service for HttpService { } let mut tasks = self.tasks.lock().unwrap(); - for server in servers { - let invoker = Arc::clone(&invoker); - let publisher = publisher.clone(); - let shutdown = self.shutdown_rx.clone(); - let name = server.name.clone(); - let port = server.port; + for config in servers { + let name = config.name.clone(); + let port = config.port; + let server = HttpServer::new(config, Arc::clone(&invoker), publisher.clone())?; - tracing::info!(server = %name, port, routes = server.routes.len(), "starting HTTP server"); + tracing::info!(server = %name, port, "starting HTTP server"); + let shutdown = self.shutdown_rx.clone(); tasks.push(tokio::spawn(async move { - if let Err(e) = - crate::server::run(port, server.routes, invoker, publisher, shutdown).await - { + if let Err(e) = server.run(shutdown).await { tracing::error!(server = %name, "HTTP server error: {e}"); } })); diff --git a/crates/opentelemetry/Cargo.toml b/crates/opentelemetry/Cargo.toml new file mode 100644 index 0000000..ab274a0 --- /dev/null +++ b/crates/opentelemetry/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "composable-otel" +version.workspace = true +description = "OpenTelemetry for Composable Runtime" +edition.workspace = true +license.workspace = true +readme = "README.md" +repository.workspace = true +categories = ["wasm"] +keywords = ["wasm", "opentelemetry"] + +[dependencies] +anyhow.workspace = true +composable-runtime = { version = "0.5.0-alpha.2", path = "../..", default-features = false } +indexmap = "2" +opentelemetry.workspace = true +opentelemetry-otlp = { workspace = true, features = ["grpc-tonic", "http-proto", "reqwest-client", "trace", "logs"] } +opentelemetry_sdk = { workspace = true, features = [ + "rt-tokio", + "experimental_trace_batch_span_processor_with_async_runtime", + "experimental_logs_batch_log_processor_with_async_runtime", + "trace", + "logs", +] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1" +tokio = { version = "1", features = ["rt"] } +tracing = "0.1" +wasmtime = { workspace = true } diff --git a/crates/opentelemetry/README.md b/crates/opentelemetry/README.md new file mode 100644 index 0000000..fd026b7 --- /dev/null +++ b/crates/opentelemetry/README.md @@ -0,0 +1,80 @@ +# Composable OpenTelemetry + +**Host capability providing `wasi:otel` to guest components.** + +Guest components can emit spans via `wasi:otel/tracing` and log records via `wasi:otel/logs` (metrics will be added soon). The host capability batches and forwards to an OTLP endpoint. + +--- + +## Configuration + +Capability instances are defined under `[capability.]` with `type="otel"` in TOML config files. + +```toml +[capability.otel] +type = "otel" +endpoint = "http://localhost:4317" +protocol = "grpc" + +[capability.otel.resource] +"service.name" = "my-service" +"service.version" = "0.1.0" +``` + +### Properties + +| Property | Default | Description | +|---|---|---| +| `endpoint` | `http://localhost:4317` | OTLP endpoint URL | +| `protocol` | `grpc` | OTLP protocol: `grpc` or `http/protobuf` | +| `resource` | `{}` | Table of resource attributes applied to spans and to log records that carry no inline resource | + +### Multiple instances + +Multiple `[capability.*]` blocks with `type = "otel"` create independent instances. Each has its own exporter pipeline (endpoint, protocol, resource). Components import a specific instance by the capability name under `[capability.]`. + +--- + +## Trace Context Propagation + +The capability exposes `outer-span-context` on `wasi:otel/tracing`, returning the `SpanContext` the host opened for the current invocation. This is parsed from a `traceparent` (and optional `tracestate`) entry on the runtime's `PROPAGATION_CONTEXT` task-local, populated by whichever entry point accepted the inbound request. For example, `composable-http-server` writes the traceparent before invoking a component. + +When no traceparent is in scope, `outer-span-context` returns an empty span context. + +--- + +## Log Record Resources + +Log records may optionally carry an inline `resource` field: + +- Records **without** a resource route through the capability's default `SdkLoggerProvider`, which carries the capability's configured `[capability.*.resource]` attributes. +- Records **with** a resource go through a per-resource `SdkLoggerProvider`, keyed by sorted attribute pairs and cached for reuse.. + +--- + +## Library usage + +Register the service with a `RuntimeBuilder`: + +```rust +use composable_runtime::Runtime; +use composable_otel::OtelService; + +let runtime = Runtime::builder() + .from_paths(&config_paths) + .with_service::() + .build() + .await?; + +runtime.run().await +``` + +The service claims `[capability.*]` definitions where `type = "otel"`. On `start()` it initializes each instance's exporters and processors. On `shutdown()` it flushes and stops the batch processors for each instance. + +--- + +## WIT + +Bindings target the [wasi:otel](https://github.com/WebAssembly/wasi-otel) `tracing` and `logs` interfaces (the `wasi:otel@0.2.0-rc.2+patch` package has updated transitive wasi dependency versions to 0.2.6 to align with the core runtime). The `metrics` interface is not yet implemented. + +See [examples/otel-service](../../examples/otel-service) for an end-to-end example including HTTP trace propagation. diff --git a/crates/opentelemetry/src/lib.rs b/crates/opentelemetry/src/lib.rs new file mode 100644 index 0000000..0659a5e --- /dev/null +++ b/crates/opentelemetry/src/lib.rs @@ -0,0 +1,604 @@ +//! OpenTelemetry host capability for composable-runtime. +//! +//! Provides `wasi:otel/logs` and `wasi:otel/tracing` as a host capability +//! backed by the OpenTelemetry Rust SDK with OTLP export. + +use anyhow::Result; +use composable_runtime::{ComponentState, HostCapability, PROPAGATION_CONTEXT, Service}; +use indexmap::IndexMap; +use opentelemetry::trace::{SpanContext, SpanId}; +use opentelemetry_otlp::{LogExporter, SpanExporter, WithExportConfig}; +use opentelemetry_sdk::{ + Resource, + logs::{SdkLoggerProvider, log_processor_with_async_runtime::BatchLogProcessor}, + runtime::Tokio, + trace::{SpanProcessor, span_processor_with_async_runtime::BatchSpanProcessor}, +}; +use serde::Deserialize; +use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; +use std::sync::{Arc, Mutex, OnceLock}; +use wasmtime::component::{HasSelf, Linker}; + +mod bindings { + wasmtime::component::bindgen!({ + path: "wit", + world: "otel-capability", + imports: { default: async | trappable }, + }); +} + +use bindings::wasi::otel; + +// Initialized per OtelCapability instance in OtelService::start(). +struct CapabilityProcessors { + span_processor: Arc>, + // Used when log-record carries no resource. All no-resource records share this processor. + default_log_provider: Arc, + // Created on demand when a log-record carries a resource. Keyed by sorted attribute pairs. + keyed_log_providers: Mutex, Arc>>, +} + +// Per-component-invocation state placed into ComponentState extensions. +struct OtelInstanceState { + // Ordered map of currently-open guest spans (span_id -> SpanContext), innermost last. + guest_spans: IndexMap, + processors: Arc, +} + +/// Configuration for the OTel capability, deserialized from `[capability.otel]` TOML. +#[derive(Deserialize)] +pub struct OtelCapability { + #[serde(default = "default_endpoint")] + pub endpoint: String, + + #[serde(default = "default_protocol")] + pub protocol: String, + + #[serde(default)] + pub resource: HashMap, + + // Initialized by OtelService::start(); not from TOML. + #[serde(skip)] + processors: OnceLock>, +} + +fn default_endpoint() -> String { + "http://localhost:4317".to_string() +} + +fn default_protocol() -> String { + "grpc".to_string() +} + +impl Default for OtelCapability { + fn default() -> Self { + Self { + endpoint: default_endpoint(), + protocol: default_protocol(), + resource: HashMap::new(), + processors: OnceLock::new(), + } + } +} + +impl OtelCapability { + // Called by OtelService::start() to build exporters and processors from this instance's config. + fn init(&self) -> Result<()> { + let resource = build_resource(&self.resource); + + let span_exporter = match self.protocol.as_str() { + "http/protobuf" => SpanExporter::builder() + .with_http() + .with_endpoint(&self.endpoint) + .build() + .map_err(|e| anyhow::anyhow!("Failed to build span exporter: {e}"))?, + _ => SpanExporter::builder() + .with_tonic() + .with_endpoint(&self.endpoint) + .build() + .map_err(|e| anyhow::anyhow!("Failed to build span exporter: {e}"))?, + }; + + let mut span_processor = BatchSpanProcessor::builder(span_exporter, Tokio).build(); + span_processor.set_resource(&resource); + + let log_exporter = match self.protocol.as_str() { + "http/protobuf" => LogExporter::builder() + .with_http() + .with_endpoint(&self.endpoint) + .build() + .map_err(|e| anyhow::anyhow!("Failed to build log exporter: {e}"))?, + _ => LogExporter::builder() + .with_tonic() + .with_endpoint(&self.endpoint) + .build() + .map_err(|e| anyhow::anyhow!("Failed to build log exporter: {e}"))?, + }; + + let default_log_provider = SdkLoggerProvider::builder() + .with_resource(resource) + .with_log_processor(BatchLogProcessor::builder(log_exporter, Tokio).build()) + .build(); + + let _ = self.processors.set(Arc::new(CapabilityProcessors { + span_processor: Arc::new(span_processor), + default_log_provider: Arc::new(default_log_provider), + keyed_log_providers: Mutex::new(HashMap::new()), + })); + + Ok(()) + } + + fn shutdown(&self) { + let Some(p) = self.processors.get() else { + return; + }; + let _ = p.span_processor.shutdown(); + let _ = p.default_log_provider.shutdown(); + for provider in p.keyed_log_providers.lock().unwrap().values() { + let _ = provider.shutdown(); + } + } +} + +impl HostCapability for OtelCapability { + fn interfaces(&self) -> Vec { + vec![ + "wasi:otel/logs@0.2.0-rc.2+patch".to_string(), + "wasi:otel/tracing@0.2.0-rc.2+patch".to_string(), + ] + } + + fn link(&self, linker: &mut Linker) -> wasmtime::Result<()> { + otel::logs::add_to_linker::<_, HasSelf<_>>(linker, |state| state)?; + otel::tracing::add_to_linker::<_, HasSelf<_>>(linker, |state| state)?; + Ok(()) + } + + composable_runtime::create_state!(this, OtelInstanceState, { + let processors = this + .processors + .get() + .expect("OtelCapability requires OtelService::start() to be called before invoke()") + .clone(); + OtelInstanceState { + guest_spans: IndexMap::new(), + processors, + } + }); +} + +impl otel::tracing::Host for ComponentState { + async fn on_start(&mut self, context: otel::tracing::SpanContext) -> wasmtime::Result<()> { + let span_context = convert_span_context(context); + let span_id = span_context.span_id(); + self.get_extension_mut::() + .expect("OtelInstanceState not initialized") + .guest_spans + .insert(span_id, span_context); + Ok(()) + } + + async fn on_end(&mut self, span: otel::tracing::SpanData) -> wasmtime::Result<()> { + let state = self + .get_extension_mut::() + .expect("OtelInstanceState not initialized"); + let span_context = convert_span_context(span.span_context.clone()); + state.guest_spans.shift_remove(&span_context.span_id()); + // Parent is remote if not in the current guest spans map. + let parent_is_remote = opentelemetry::trace::SpanId::from_hex(&span.parent_span_id) + .ok() + .filter(|pid| *pid != opentelemetry::trace::SpanId::INVALID) + .map(|pid| !state.guest_spans.contains_key(&pid)) + .unwrap_or(false); + state + .processors + .span_processor + .on_end(convert_span_data(span, parent_is_remote)); + Ok(()) + } + + async fn outer_span_context(&mut self) -> wasmtime::Result { + let sc = PROPAGATION_CONTEXT + .try_with(|ctx| { + ctx.as_ref().and_then(|c| { + let traceparent = c.entries.get("traceparent")?; + let tracestate = c.entries.get("tracestate").map(|s| s.as_str()); + parse_traceparent(traceparent, tracestate) + }) + }) + .ok() + .flatten(); + Ok(sc.unwrap_or_else(|| { + otel_span_context_to_wasi(opentelemetry::trace::SpanContext::empty_context()) + })) + } +} + +impl otel::logs::Host for ComponentState { + async fn on_emit(&mut self, data: otel::logs::LogRecord) -> wasmtime::Result<()> { + use opentelemetry::logs::{Logger, LoggerProvider}; + + let state = self + .get_extension_mut::() + .expect("OtelInstanceState not initialized"); + + let provider: Arc = match &data.resource { + None => Arc::clone(&state.processors.default_log_provider), + Some(r) => { + let key = resource_key(r); + let mut map = state.processors.keyed_log_providers.lock().unwrap(); + if let Some(p) = map.get(&key) { + Arc::clone(p) + } else { + let new_provider = Arc::new( + SdkLoggerProvider::builder() + .with_resource(wasi_resource_to_sdk(r)) + .build(), + ); + map.insert(key, Arc::clone(&new_provider)); + new_provider + } + } + }; + + let scope = extract_instrumentation_scope(&data); + let logger = provider.logger_with_scope(scope); + let mut record = logger.create_log_record(); + populate_log_record(&mut record, &data); + logger.emit(record); + + Ok(()) + } +} + +/// Service that owns all `OtelCapability` instances and manages their lifecycle. +pub struct OtelService { + instances: Arc>>>, +} + +impl Default for OtelService { + fn default() -> Self { + Self { + instances: Arc::new(Mutex::new(Vec::new())), + } + } +} + +impl Service for OtelService { + fn capabilities(&self) -> Vec<(&'static str, composable_runtime::HostCapabilityFactory)> { + let instances = Arc::clone(&self.instances); + vec![composable_runtime::create_capability!("otel", |config| { + let cap = + Arc::new(serde_json::from_value::(config).unwrap_or_default()); + instances.lock().unwrap().push(Arc::clone(&cap)); + OtelCapabilityHandle(cap) + })] + } + + fn start(&self) -> Result<()> { + for cap in self.instances.lock().unwrap().iter() { + cap.init()?; + } + Ok(()) + } + + fn shutdown(&self) -> Pin + Send + '_>> { + Box::pin(async move { + let caps: Vec<_> = self.instances.lock().unwrap().clone(); + for cap in caps { + // spawn_blocking since BatchSpanProcessor::shutdown() calls block_on internally. + let _ = tokio::task::spawn_blocking(move || cap.shutdown()).await; + } + }) + } +} + +// Wraps Arc so it can be returned as Box. +struct OtelCapabilityHandle(Arc); + +impl HostCapability for OtelCapabilityHandle { + fn interfaces(&self) -> Vec { + self.0.interfaces() + } + + fn link(&self, linker: &mut Linker) -> wasmtime::Result<()> { + self.0.link(linker) + } + + fn create_state_boxed( + &self, + ) -> Result)>> { + self.0.create_state_boxed() + } +} + +// Parses a W3C `traceparent` header and optional `tracestate` into a wasi SpanContext. +// Returns None if the traceparent value is malformed. +fn parse_traceparent( + traceparent: &str, + tracestate: Option<&str>, +) -> Option { + let parts: Vec<&str> = traceparent.splitn(4, '-').collect(); + if parts.len() != 4 { + return None; + } + let trace_id = opentelemetry::trace::TraceId::from_hex(parts[1]).ok()?; + let span_id = opentelemetry::trace::SpanId::from_hex(parts[2]).ok()?; + let flags = u8::from_str_radix(parts[3], 16).ok()?; + let trace_flags = if flags & 0x01 != 0 { + otel::tracing::TraceFlags::SAMPLED + } else { + otel::tracing::TraceFlags::empty() + }; + let trace_state = tracestate + .unwrap_or("") + .split(',') + .filter_map(|s| { + s.split_once('=') + .map(|(k, v)| (k.to_string(), v.to_string())) + }) + .collect(); + Some(otel::tracing::SpanContext { + trace_id: format!("{:032x}", trace_id), + span_id: format!("{:016x}", span_id), + trace_flags, + is_remote: true, + trace_state, + }) +} + +fn build_resource(attrs: &HashMap) -> Resource { + let kvs: Vec = attrs + .iter() + .map(|(k, v)| opentelemetry::KeyValue::new(k.clone(), v.clone())) + .collect(); + Resource::builder().with_attributes(kvs).build() +} + +fn wasi_resource_to_sdk(r: &otel::logs::Resource) -> Resource { + let kvs: Vec = r + .attributes + .iter() + .map(|kv| opentelemetry::KeyValue::new(kv.key.clone(), kv.value.clone())) + .collect(); + Resource::builder().with_attributes(kvs).build() +} + +fn resource_key(r: &otel::logs::Resource) -> Vec<(String, String)> { + let mut pairs: Vec<(String, String)> = r + .attributes + .iter() + .map(|kv| (kv.key.clone(), kv.value.clone())) + .collect(); + pairs.sort_unstable_by(|a, b| a.0.cmp(&b.0)); + pairs +} + +fn populate_log_record( + record: &mut opentelemetry_sdk::logs::SdkLogRecord, + data: &otel::logs::LogRecord, +) { + use opentelemetry::logs::LogRecord as _; + + if let Some(body) = &data.body { + record.set_body(opentelemetry::logs::AnyValue::String(body.clone().into())); + } + if let Some(ts) = data.timestamp { + record.set_timestamp(convert_datetime(ts)); + } + if let Some(ts) = data.observed_timestamp { + record.set_observed_timestamp(convert_datetime(ts)); + } + if let Some(n) = data.severity_number { + record.set_severity_number(severity_from_u8(n)); + } + if let Some(t) = &data.severity_text { + record.set_severity_text(Box::leak(t.clone().into_boxed_str())); + } + if let Some(name) = &data.event_name { + record.set_event_name(Box::leak(name.clone().into_boxed_str())); + } + if let (Some(trace_id), Some(span_id)) = (&data.trace_id, &data.span_id) + && let (Ok(tid), Ok(sid)) = ( + opentelemetry::trace::TraceId::from_hex(trace_id), + opentelemetry::trace::SpanId::from_hex(span_id), + ) + { + record.set_trace_context( + tid, + sid, + data.trace_flags.map(|f| { + if f.contains(otel::logs::TraceFlags::SAMPLED) { + opentelemetry::trace::TraceFlags::SAMPLED + } else { + opentelemetry::trace::TraceFlags::default() + } + }), + ); + } +} + +fn extract_instrumentation_scope( + data: &otel::logs::LogRecord, +) -> opentelemetry::InstrumentationScope { + let Some(s) = &data.instrumentation_scope else { + return opentelemetry::InstrumentationScope::default(); + }; + let mut builder = + opentelemetry::InstrumentationScope::builder(std::borrow::Cow::Owned(s.name.clone())); + if let Some(v) = &s.version { + builder = builder.with_version(v.clone()); + } + if let Some(url) = &s.schema_url { + builder = builder.with_schema_url(std::borrow::Cow::Owned(url.clone())); + } + builder.build() +} + +fn convert_span_context(sc: otel::tracing::SpanContext) -> opentelemetry::trace::SpanContext { + let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) + .unwrap_or(opentelemetry::trace::TraceId::INVALID); + let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID); + let trace_flags = if sc.trace_flags.contains(otel::tracing::TraceFlags::SAMPLED) { + opentelemetry::trace::TraceFlags::SAMPLED + } else { + opentelemetry::trace::TraceFlags::default() + }; + let trace_state = + opentelemetry::trace::TraceState::from_key_value(sc.trace_state).unwrap_or_default(); + opentelemetry::trace::SpanContext::new( + trace_id, + span_id, + trace_flags, + sc.is_remote, + trace_state, + ) +} + +fn otel_span_context_to_wasi(sc: opentelemetry::trace::SpanContext) -> otel::tracing::SpanContext { + otel::tracing::SpanContext { + trace_id: format!("{:032x}", sc.trace_id()), + span_id: format!("{:016x}", sc.span_id()), + trace_flags: if sc.trace_flags().is_sampled() { + otel::tracing::TraceFlags::SAMPLED + } else { + otel::tracing::TraceFlags::empty() + }, + is_remote: sc.is_remote(), + trace_state: sc + .trace_state() + .header() + .split(',') + .filter_map(|s| { + s.split_once('=') + .map(|(k, v)| (k.to_string(), v.to_string())) + }) + .collect(), + } +} + +fn convert_span_data( + span: otel::tracing::SpanData, + parent_is_remote: bool, +) -> opentelemetry_sdk::trace::SpanData { + use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; + + let mut events = SpanEvents::default(); + events.events = span.events.into_iter().map(convert_event).collect(); + events.dropped_count = span.dropped_events; + + let mut links = SpanLinks::default(); + links.links = span.links.into_iter().map(convert_link).collect(); + links.dropped_count = span.dropped_links; + + opentelemetry_sdk::trace::SpanData { + span_context: convert_span_context(span.span_context), + parent_span_id: opentelemetry::trace::SpanId::from_hex(&span.parent_span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID), + parent_span_is_remote: parent_is_remote, + span_kind: convert_span_kind(span.span_kind), + name: span.name.into(), + start_time: convert_datetime(span.start_time), + end_time: convert_datetime(span.end_time), + attributes: span.attributes.into_iter().map(convert_key_value).collect(), + dropped_attributes_count: span.dropped_attributes, + events, + links, + status: convert_status(span.status), + instrumentation_scope: convert_instrumentation_scope_tracing(span.instrumentation_scope), + } +} + +fn convert_event(e: otel::tracing::Event) -> opentelemetry::trace::Event { + opentelemetry::trace::Event::new( + e.name, + convert_datetime(e.time), + e.attributes.into_iter().map(convert_key_value).collect(), + 0, + ) +} + +fn convert_link(l: otel::tracing::Link) -> opentelemetry::trace::Link { + opentelemetry::trace::Link::new( + convert_span_context(l.span_context), + l.attributes.into_iter().map(convert_key_value).collect(), + 0, + ) +} + +fn convert_span_kind(kind: otel::tracing::SpanKind) -> opentelemetry::trace::SpanKind { + match kind { + otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, + otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, + otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, + otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, + otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, + } +} + +fn convert_status(status: otel::tracing::Status) -> opentelemetry::trace::Status { + match status { + otel::tracing::Status::Unset => opentelemetry::trace::Status::Unset, + otel::tracing::Status::Ok => opentelemetry::trace::Status::Ok, + otel::tracing::Status::Error(s) => opentelemetry::trace::Status::Error { + description: s.into(), + }, + } +} + +fn convert_key_value(kv: otel::tracing::KeyValue) -> opentelemetry::KeyValue { + opentelemetry::KeyValue::new(kv.key, kv.value) +} + +fn convert_datetime(dt: bindings::wasi::clocks::wall_clock::Datetime) -> std::time::SystemTime { + std::time::UNIX_EPOCH + std::time::Duration::new(dt.seconds, dt.nanoseconds) +} + +fn convert_instrumentation_scope_tracing( + scope: otel::tracing::InstrumentationScope, +) -> opentelemetry::InstrumentationScope { + let mut builder = + opentelemetry::InstrumentationScope::builder(std::borrow::Cow::Owned(scope.name)); + if let Some(v) = scope.version { + builder = builder.with_version(v); + } + if let Some(url) = scope.schema_url { + builder = builder.with_schema_url(std::borrow::Cow::Owned(url)); + } + builder.build() +} + +fn severity_from_u8(n: u8) -> opentelemetry::logs::Severity { + use opentelemetry::logs::Severity::*; + match n { + 1 => Trace, + 2 => Trace2, + 3 => Trace3, + 4 => Trace4, + 5 => Debug, + 6 => Debug2, + 7 => Debug3, + 8 => Debug4, + 9 => Info, + 10 => Info2, + 11 => Info3, + 12 => Info4, + 13 => Warn, + 14 => Warn2, + 15 => Warn3, + 16 => Warn4, + 17 => Error, + 18 => Error2, + 19 => Error3, + 20 => Error4, + 21 => Fatal, + 22 => Fatal2, + 23 => Fatal3, + 24 => Fatal4, + _ => Info, + } +} diff --git a/examples/otel/wit/deps/wasi-clocks-0.2.6/package.wit b/crates/opentelemetry/wit/deps/wasi-clocks-0.2.6/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-clocks-0.2.6/package.wit rename to crates/opentelemetry/wit/deps/wasi-clocks-0.2.6/package.wit diff --git a/crates/opentelemetry/wit/deps/wasi-io-0.2.6/package.wit b/crates/opentelemetry/wit/deps/wasi-io-0.2.6/package.wit new file mode 100644 index 0000000..99ec5b3 --- /dev/null +++ b/crates/opentelemetry/wit/deps/wasi-io-0.2.6/package.wit @@ -0,0 +1,11 @@ +package wasi:io@0.2.6; + +interface poll { + resource pollable { + ready: func() -> bool; + block: func(); + } + + poll: func(in: list>) -> list; +} + diff --git a/examples/otel/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit b/crates/opentelemetry/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit rename to crates/opentelemetry/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit diff --git a/examples/otel/wit/overrides/wasi-otel/logs.wit b/crates/opentelemetry/wit/overrides/wasi-otel/logs.wit similarity index 100% rename from examples/otel/wit/overrides/wasi-otel/logs.wit rename to crates/opentelemetry/wit/overrides/wasi-otel/logs.wit diff --git a/examples/otel/wit/overrides/wasi-otel/metrics.wit b/crates/opentelemetry/wit/overrides/wasi-otel/metrics.wit similarity index 100% rename from examples/otel/wit/overrides/wasi-otel/metrics.wit rename to crates/opentelemetry/wit/overrides/wasi-otel/metrics.wit diff --git a/examples/otel/wit/overrides/wasi-otel/tracing.wit b/crates/opentelemetry/wit/overrides/wasi-otel/tracing.wit similarity index 100% rename from examples/otel/wit/overrides/wasi-otel/tracing.wit rename to crates/opentelemetry/wit/overrides/wasi-otel/tracing.wit diff --git a/examples/otel/wit/overrides/wasi-otel/types.wit b/crates/opentelemetry/wit/overrides/wasi-otel/types.wit similarity index 100% rename from examples/otel/wit/overrides/wasi-otel/types.wit rename to crates/opentelemetry/wit/overrides/wasi-otel/types.wit diff --git a/examples/otel/wit/overrides/wasi-otel/world.wit b/crates/opentelemetry/wit/overrides/wasi-otel/world.wit similarity index 100% rename from examples/otel/wit/overrides/wasi-otel/world.wit rename to crates/opentelemetry/wit/overrides/wasi-otel/world.wit diff --git a/crates/opentelemetry/wit/package.wit b/crates/opentelemetry/wit/package.wit new file mode 100644 index 0000000..ae79836 --- /dev/null +++ b/crates/opentelemetry/wit/package.wit @@ -0,0 +1,7 @@ +package modulewise:otel@0.1.0; + +world otel-capability { + import wasi:otel/logs@0.2.0-rc.2+patch; + import wasi:otel/tracing@0.2.0-rc.2+patch; + import wasi:otel/types@0.2.0-rc.2+patch; +} diff --git a/crates/opentelemetry/wkg.lock b/crates/opentelemetry/wkg.lock new file mode 100644 index 0000000..626a130 --- /dev/null +++ b/crates/opentelemetry/wkg.lock @@ -0,0 +1,12 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:clocks" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.6" +version = "0.2.6" +digest = "sha256:569984cc45d3f5a362a3b2897aabbaa3cc4184a6113bfcbbf03c1bd7fc20338c" diff --git a/crates/opentelemetry/wkg.toml b/crates/opentelemetry/wkg.toml new file mode 100644 index 0000000..aa772d3 --- /dev/null +++ b/crates/opentelemetry/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"wasi:otel" = { path = "./wit/overrides/wasi-otel" } diff --git a/examples/host-capability/Cargo.lock b/examples/host-capability/Cargo.lock index 6f7bf09..4a50f42 100644 --- a/examples/host-capability/Cargo.lock +++ b/examples/host-capability/Cargo.lock @@ -652,7 +652,7 @@ dependencies = [ [[package]] name = "composable-interceptor" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -666,7 +666,7 @@ dependencies = [ [[package]] name = "composable-runtime" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", diff --git a/examples/host-capability/host/src/main.rs b/examples/host-capability/host/src/main.rs index 852fc23..963e1f2 100644 --- a/examples/host-capability/host/src/main.rs +++ b/examples/host-capability/host/src/main.rs @@ -41,7 +41,14 @@ async fn main() -> Result<()> { .await?; let result = runtime - .invoke("greeter", "greet", vec![serde_json::json!("World")]) + .invoker() + .invoke( + "greeter", + "greet", + vec![serde_json::json!("World")], + None, + None, + ) .await?; println!("Result: {}", result); diff --git a/examples/otel/Cargo.lock b/examples/otel-components/Cargo.lock similarity index 99% rename from examples/otel/Cargo.lock rename to examples/otel-components/Cargo.lock index 6ecc71d..272ee69 100644 --- a/examples/otel/Cargo.lock +++ b/examples/otel-components/Cargo.lock @@ -695,7 +695,7 @@ dependencies = [ [[package]] name = "composable-interceptor" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "composable-runtime" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", diff --git a/examples/otel/Cargo.toml b/examples/otel-components/Cargo.toml similarity index 100% rename from examples/otel/Cargo.toml rename to examples/otel-components/Cargo.toml diff --git a/examples/otel/README.md b/examples/otel-components/README.md similarity index 99% rename from examples/otel/README.md rename to examples/otel-components/README.md index 06b50ae..c2685f2 100644 --- a/examples/otel/README.md +++ b/examples/otel-components/README.md @@ -1,4 +1,4 @@ -# OpenTelemetry Example +# OpenTelemetry Example using Components This example demonstrates sending OpenTelemetry logs from a guest wasm component to an OTLP-compatible collector via the [wasi:otel](https://github.com/WebAssembly/wasi-otel) WIT interface and a gRPC endpoint interface. Tracing and metrics will be added to the demo in a future update. diff --git a/examples/otel/build.sh b/examples/otel-components/build.sh similarity index 100% rename from examples/otel/build.sh rename to examples/otel-components/build.sh diff --git a/examples/otel/config-with-components.toml b/examples/otel-components/config-with-components.toml similarity index 100% rename from examples/otel/config-with-components.toml rename to examples/otel-components/config-with-components.toml diff --git a/examples/otel/config-with-host-capability.toml b/examples/otel-components/config-with-host-capability.toml similarity index 100% rename from examples/otel/config-with-host-capability.toml rename to examples/otel-components/config-with-host-capability.toml diff --git a/examples/otel/grpc-capability/Cargo.toml b/examples/otel-components/grpc-capability/Cargo.toml similarity index 100% rename from examples/otel/grpc-capability/Cargo.toml rename to examples/otel-components/grpc-capability/Cargo.toml diff --git a/examples/otel/grpc-capability/src/lib.rs b/examples/otel-components/grpc-capability/src/lib.rs similarity index 100% rename from examples/otel/grpc-capability/src/lib.rs rename to examples/otel-components/grpc-capability/src/lib.rs diff --git a/examples/otel/grpc-capability/wit/grpc.wit b/examples/otel-components/grpc-capability/wit/grpc.wit similarity index 100% rename from examples/otel/grpc-capability/wit/grpc.wit rename to examples/otel-components/grpc-capability/wit/grpc.wit diff --git a/examples/otel/grpc-to-http/Cargo.toml b/examples/otel-components/grpc-to-http/Cargo.toml similarity index 100% rename from examples/otel/grpc-to-http/Cargo.toml rename to examples/otel-components/grpc-to-http/Cargo.toml diff --git a/examples/otel/grpc-to-http/src/lib.rs b/examples/otel-components/grpc-to-http/src/lib.rs similarity index 100% rename from examples/otel/grpc-to-http/src/lib.rs rename to examples/otel-components/grpc-to-http/src/lib.rs diff --git a/examples/otel/guest/Cargo.toml b/examples/otel-components/guest/Cargo.toml similarity index 100% rename from examples/otel/guest/Cargo.toml rename to examples/otel-components/guest/Cargo.toml diff --git a/examples/otel/guest/src/lib.rs b/examples/otel-components/guest/src/lib.rs similarity index 100% rename from examples/otel/guest/src/lib.rs rename to examples/otel-components/guest/src/lib.rs diff --git a/examples/otel/host/Cargo.toml b/examples/otel-components/host/Cargo.toml similarity index 100% rename from examples/otel/host/Cargo.toml rename to examples/otel-components/host/Cargo.toml diff --git a/examples/otel/host/src/main.rs b/examples/otel-components/host/src/main.rs similarity index 82% rename from examples/otel/host/src/main.rs rename to examples/otel-components/host/src/main.rs index 8a1823c..407ed84 100644 --- a/examples/otel/host/src/main.rs +++ b/examples/otel-components/host/src/main.rs @@ -24,7 +24,14 @@ async fn main() -> Result<()> { let message = format!("testing {}", config_file); let result = runtime - .invoke("guest", "test.log", vec![serde_json::json!(message)]) + .invoker() + .invoke( + "guest", + "test.log", + vec![serde_json::json!(message)], + None, + None, + ) .await?; println!("Result: {}", result); diff --git a/examples/otel/otel-to-grpc/Cargo.toml b/examples/otel-components/otel-to-grpc/Cargo.toml similarity index 100% rename from examples/otel/otel-to-grpc/Cargo.toml rename to examples/otel-components/otel-to-grpc/Cargo.toml diff --git a/examples/otel/otel-to-grpc/src/lib.rs b/examples/otel-components/otel-to-grpc/src/lib.rs similarity index 100% rename from examples/otel/otel-to-grpc/src/lib.rs rename to examples/otel-components/otel-to-grpc/src/lib.rs diff --git a/examples/otel/run.sh b/examples/otel-components/run.sh similarity index 100% rename from examples/otel/run.sh rename to examples/otel-components/run.sh diff --git a/examples/otel/wit/deps/modulewise-grpc-0.1.0/package.wit b/examples/otel-components/wit/deps/modulewise-grpc-0.1.0/package.wit similarity index 100% rename from examples/otel/wit/deps/modulewise-grpc-0.1.0/package.wit rename to examples/otel-components/wit/deps/modulewise-grpc-0.1.0/package.wit diff --git a/examples/otel/wit/deps/wasi-cli-0.2.6/package.wit b/examples/otel-components/wit/deps/wasi-cli-0.2.6/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-cli-0.2.6/package.wit rename to examples/otel-components/wit/deps/wasi-cli-0.2.6/package.wit diff --git a/examples/otel-components/wit/deps/wasi-clocks-0.2.6/package.wit b/examples/otel-components/wit/deps/wasi-clocks-0.2.6/package.wit new file mode 100644 index 0000000..d638f1a --- /dev/null +++ b/examples/otel-components/wit/deps/wasi-clocks-0.2.6/package.wit @@ -0,0 +1,157 @@ +package wasi:clocks@0.2.6; + +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +@since(version = 0.2.0) +interface monotonic-clock { + @since(version = 0.2.0) + use wasi:io/poll@0.2.6.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + @since(version = 0.2.0) + type instant = u64; + + /// A duration of time, in nanoseconds. + @since(version = 0.2.0) + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + @since(version = 0.2.0) + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + @since(version = 0.2.0) + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// has occurred. + @since(version = 0.2.0) + subscribe-instant: func(when: instant) -> pollable; + + /// Create a `pollable` that will resolve after the specified duration has + /// elapsed from the time this function is invoked. + @since(version = 0.2.0) + subscribe-duration: func(when: duration) -> pollable; +} + +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +@since(version = 0.2.0) +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + @since(version = 0.2.0) + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + @since(version = 0.2.0) + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + @since(version = 0.2.0) + resolution: func() -> datetime; +} + +@unstable(feature = clocks-timezone) +interface timezone { + @unstable(feature = clocks-timezone) + use wall-clock.{datetime}; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + @unstable(feature = clocks-timezone) + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + @unstable(feature = clocks-timezone) + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + @unstable(feature = clocks-timezone) + utc-offset: func(when: datetime) -> s32; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/poll@0.2.6; + @since(version = 0.2.0) + import monotonic-clock; + @since(version = 0.2.0) + import wall-clock; + @unstable(feature = clocks-timezone) + import timezone; +} diff --git a/examples/otel/wit/deps/wasi-config-0.2.0-rc.1/package.wit b/examples/otel-components/wit/deps/wasi-config-0.2.0-rc.1/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-config-0.2.0-rc.1/package.wit rename to examples/otel-components/wit/deps/wasi-config-0.2.0-rc.1/package.wit diff --git a/examples/otel/wit/deps/wasi-http-0.2.6/package.wit b/examples/otel-components/wit/deps/wasi-http-0.2.6/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-http-0.2.6/package.wit rename to examples/otel-components/wit/deps/wasi-http-0.2.6/package.wit diff --git a/examples/otel/wit/deps/wasi-io-0.2.6/package.wit b/examples/otel-components/wit/deps/wasi-io-0.2.6/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-io-0.2.6/package.wit rename to examples/otel-components/wit/deps/wasi-io-0.2.6/package.wit diff --git a/examples/otel-components/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit b/examples/otel-components/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit new file mode 100644 index 0000000..7230063 --- /dev/null +++ b/examples/otel-components/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit @@ -0,0 +1,473 @@ +/// patched to use 0.2.6 instead of 0.2.0 for wasi:clocks and wasi:io +package wasi:otel@0.2.0-rc.2+patch; + +interface types { + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + /// + /// This corresponds with the `AnyValue` type defined in the [attribute spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue). + /// Because WIT doesn't support recursive types, the data needs to be serialized. JSON is used as the encoding format. + /// + /// Byte arrays require special encoding since JSON cannot distinguish them from number arrays. + /// They are base64-encoded with a prefix that follows the Data URI RFC 2397 convention: + /// `data:application/octet-stream;base64,` + type value = string; + + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// An immutable representation of the entity producing telemetry as attributes. + record %resource { + /// Attributes that identify the resource. + attributes: list, + /// The schema URL to be recorded in the emitted resource. + schema-url: option, + } + + /// Describes the instrumentation scope that produced telemetry. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + /// The library version. + version: option, + /// Schema URL used by this library. + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + schema-url: option, + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} + +interface tracing { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use types.{key-value, instrumentation-scope}; + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal, + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + /// Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; +} + +interface logs { + use types.{instrumentation-scope, %resource, value, key-value}; + use tracing.{span-id, trace-id, trace-flags}; + use wasi:clocks/wall-clock@0.2.6.{datetime}; + + /// Represents the recording of an event. + record log-record { + /// Time when the event occurred. + timestamp: option, + /// Time when the event was observed. + observed-timestamp: option, + /// The severity text(also known as log level). + severity-text: option, + /// The numerical value of the severity ranging from 1-24. + severity-number: option, + /// The body of the log record. + body: option, + /// Additional information about the specific event occurrence. + attributes: option>, + /// Name that identifies the class / type of event. + event-name: option, + /// Describes the source of the log. + %resource: option<%resource>, + /// Describes the scope that emitted the log. + instrumentation-scope: option, + /// Request trace id. + trace-id: option, + /// Request span id. + span-id: option, + /// W3C trace flag. + trace-flags: option, + } + + /// Called when a log is emitted. + on-emit: func(data: log-record); +} + +interface metrics { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use wasi:clocks/monotonic-clock@0.2.6.{duration}; + use types.{key-value, instrumentation-scope, %resource}; + use tracing.{span-id, trace-id}; + + /// An error resulting from `export` being called. + type error = string; + + /// A set of bucket counts, encoded in a contiguous array of counts. + record exponential-bucket { + /// The bucket index of the first entry in the `counts` list. + offset: s32, + /// A list where `counts[i]` carries the count of the bucket at index `offset + i`. + /// + /// `counts[i]` is the count of values greater than base^(offset+i) and less than + /// or equal to base^(offset+i+1). + counts: list, + } + + /// Defines the window that an aggregation was calculated over. + enum temporality { + /// A measurement interval that continues to expand forward in time from a + /// starting point. + /// + /// New measurements are added to all previous measurements since a start time. + /// + /// This is the default temporality. + cumulative, + /// A measurement interval that resets each cycle. + /// + /// Measurements from one cycle are recorded independently, measurements from + /// other cycles do not affect them. + delta, + /// Configures Synchronous Counter and Histogram instruments to use + /// Delta aggregation temporality, which allows them to shed memory + /// following a cardinality explosion, thus use less memory. + low-memory, + } + + /// The number types available for any given instrument. + variant metric-number { + %f64(f64), + %s64(s64), + %u64(u64), + } + + /// A measurement sampled from a time series providing a typical example. + record exemplar { + /// The attributes recorded with the measurement but filtered out of the + /// time series' aggregated data. + filtered-attributes: list, + /// The time when the measurement was recorded. + time: datetime, + /// The measured value. + value: metric-number, + /// The ID of the span that was active during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + span-id: span-id, + /// The ID of the trace the active span belonged to during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + trace-id: trace-id, + } + + /// A single data point in a time series to be associated with a `gauge`. + record gauge-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// A measurement of the current value of an instrument. + record gauge { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: option, + /// The time when the time series was recorded. + time: datetime, + } + + /// A single data point in a time series to be associated with a `sum`. + record sum-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the sum of all measurements of values from an instrument. + record sum { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + /// Whether this aggregation only increases or decreases. + is-monotonic: bool, + } + + /// A single data point in a time series to be associated with a `histogram`. + record histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The upper bounds of the buckets of the histogram. + bounds: list, + /// The count of each of the buckets. + bucket-counts: list, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The sum of the values recorded + sum: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the histogram of all measurements of values from an instrument. + record histogram { + /// Individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with an `exponential-histogram `. + record exponential-histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The maximum value recorded. + sum: metric-number, + /// Describes the resolution of the histogram. + /// + /// Boundaries are located at powers of the base, where: + /// + /// base = 2 ^ (2 ^ -scale) + scale: s8, + /// The number of values whose absolute value is less than or equal to + /// `zero_threshold`. + /// + /// When `zero_threshold` is `0`, this is the number of values that cannot be + /// expressed using the standard exponential formula as well as values that have + /// been rounded to zero. + zero-count: u64, + /// The range of positive value bucket counts. + positive-bucket: exponential-bucket, + /// The range of negative value bucket counts. + negative-bucket: exponential-bucket, + /// The width of the zero region. + /// + /// Where the zero region is defined as the closed interval + /// [-zero_threshold, zero_threshold]. + zero-threshold: f64, + /// The sampled exemplars collected during the time series. + exemplars: list, + } + + /// The histogram of all measurements of values from an instrument. + record exponential-histogram { + /// The individual aggregated measurements with unique attributes. + data-points: list, + /// When the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// Metric data for all types. + variant metric-data { + /// Metric data for an f64 gauge. + f64-gauge(gauge), + /// Metric data for an f64 sum. + f64-sum(sum), + /// Metric data for an f64 histogram. + f64-histogram(histogram), + /// Metric data for an f64 exponential-histogram. + f64-exponential-histogram(exponential-histogram), + /// Metric data for an u64 gauge. + u64-gauge(gauge), + /// Metric data for an u64 sum. + u64-sum(sum), + /// Metric data for an u64 histogram. + u64-histogram(histogram), + /// Metric data for an u64 exponential-histogram. + u64-exponential-histogram(exponential-histogram), + /// Metric data for an s64 gauge. + s64-gauge(gauge), + /// Metric data for an s64 sum. + s64-sum(sum), + /// Metric data for an s64 histogram. + s64-histogram(histogram), + /// Metric data for an s64 exponential-histogram. + s64-exponential-histogram(exponential-histogram), + } + + /// A collection of one or more aggregated time series from a metric. + record metric { + /// The name of the metric that created this data. + name: string, + /// The description of the metric, which can be used in documentation. + description: string, + /// The unit in which the metric reports. + unit: string, + /// The aggregated data from a metric. + data: metric-data, + } + + /// A collection of `metric`s produced by a meter. + record scope-metrics { + /// The instrumentation scope that the meter was created with. + scope: instrumentation-scope, + /// The list of aggregations created by the meter. + metrics: list, + } + + /// A collection of `scope-metrics` and the associated `resource` that created them. + record resource-metrics { + /// The entity that collected the metrics. + %resource: %resource, + /// The collection of metrics with unique `instrumentation-scope`s. + scope-metrics: list, + } + + /// Exports a resource's metric data. + %export: func(metrics: resource-metrics) -> result<_, error>; +} + +world imports { + import types; + import wasi:clocks/wall-clock@0.2.6; + import tracing; + import wasi:io/poll@0.2.6; + import wasi:clocks/monotonic-clock@0.2.6; + import metrics; + import logs; +} diff --git a/examples/otel/wit/deps/wasi-random-0.2.6/package.wit b/examples/otel-components/wit/deps/wasi-random-0.2.6/package.wit similarity index 100% rename from examples/otel/wit/deps/wasi-random-0.2.6/package.wit rename to examples/otel-components/wit/deps/wasi-random-0.2.6/package.wit diff --git a/examples/otel/wit/otel.wit b/examples/otel-components/wit/otel.wit similarity index 100% rename from examples/otel/wit/otel.wit rename to examples/otel-components/wit/otel.wit diff --git a/examples/otel/wit/overrides/modulewise-grpc/package.wit b/examples/otel-components/wit/overrides/modulewise-grpc/package.wit similarity index 100% rename from examples/otel/wit/overrides/modulewise-grpc/package.wit rename to examples/otel-components/wit/overrides/modulewise-grpc/package.wit diff --git a/examples/otel-components/wit/overrides/wasi-otel/logs.wit b/examples/otel-components/wit/overrides/wasi-otel/logs.wit new file mode 100644 index 0000000..69f133c --- /dev/null +++ b/examples/otel-components/wit/overrides/wasi-otel/logs.wit @@ -0,0 +1,36 @@ +interface logs { + use types.{instrumentation-scope, %resource, value, key-value}; + use tracing.{span-id, trace-id, trace-flags}; + use wasi:clocks/wall-clock@0.2.6.{datetime}; + + /// Called when a log is emitted. + on-emit: func(data: log-record); + + /// Represents the recording of an event. + record log-record { + /// Time when the event occurred. + timestamp: option, + /// Time when the event was observed. + observed-timestamp: option, + /// The severity text(also known as log level). + severity-text: option, + /// The numerical value of the severity ranging from 1-24. + severity-number: option, + /// The body of the log record. + body: option, + /// Additional information about the specific event occurrence. + attributes: option>, + /// Name that identifies the class / type of event. + event-name: option, + /// Describes the source of the log. + %resource: option<%resource>, + /// Describes the scope that emitted the log. + instrumentation-scope: option, + /// Request trace id. + trace-id: option, + /// Request span id. + span-id: option, + /// W3C trace flag. + trace-flags: option, + } +} diff --git a/examples/otel-components/wit/overrides/wasi-otel/metrics.wit b/examples/otel-components/wit/overrides/wasi-otel/metrics.wit new file mode 100644 index 0000000..8ba58c7 --- /dev/null +++ b/examples/otel-components/wit/overrides/wasi-otel/metrics.wit @@ -0,0 +1,256 @@ +interface metrics { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use wasi:clocks/monotonic-clock@0.2.6.{duration}; + use types.{key-value, instrumentation-scope, %resource}; + use tracing.{span-id, trace-id}; + + /// Exports a resource's metric data. + %export: func(metrics: resource-metrics) -> result<_, error>; + + /// An error resulting from `export` being called. + type error = string; + + /// A collection of `scope-metrics` and the associated `resource` that created them. + record resource-metrics { + /// The entity that collected the metrics. + %resource: %resource, + /// The collection of metrics with unique `instrumentation-scope`s. + scope-metrics: list, + } + + /// A collection of `metric`s produced by a meter. + record scope-metrics { + /// The instrumentation scope that the meter was created with. + scope: instrumentation-scope, + /// The list of aggregations created by the meter. + metrics: list, + } + + /// A collection of one or more aggregated time series from a metric. + record metric { + /// The name of the metric that created this data. + name: string, + /// The description of the metric, which can be used in documentation. + description: string, + /// The unit in which the metric reports. + unit: string, + /// The aggregated data from a metric. + data: metric-data + } + + /// Metric data for all types. + variant metric-data { + /// Metric data for an f64 gauge. + f64-gauge(gauge), + /// Metric data for an f64 sum. + f64-sum(sum), + /// Metric data for an f64 histogram. + f64-histogram(histogram), + /// Metric data for an f64 exponential-histogram. + f64-exponential-histogram(exponential-histogram), + /// Metric data for an u64 gauge. + u64-gauge(gauge), + /// Metric data for an u64 sum. + u64-sum(sum), + /// Metric data for an u64 histogram. + u64-histogram(histogram), + /// Metric data for an u64 exponential-histogram. + u64-exponential-histogram(exponential-histogram), + /// Metric data for an s64 gauge. + s64-gauge(gauge), + /// Metric data for an s64 sum. + s64-sum(sum), + /// Metric data for an s64 histogram. + s64-histogram(histogram), + /// Metric data for an s64 exponential-histogram. + s64-exponential-histogram(exponential-histogram), + } + + /// A measurement of the current value of an instrument. + record gauge { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: option, + /// The time when the time series was recorded. + time: datetime, + } + + /// A single data point in a time series to be associated with a `gauge`. + record gauge-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the sum of all measurements of values from an instrument. + record sum { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + /// Whether this aggregation only increases or decreases. + is-monotonic: bool, + } + + /// A single data point in a time series to be associated with a `sum`. + record sum-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the histogram of all measurements of values from an instrument. + record histogram { + /// Individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with a `histogram`. + record histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The upper bounds of the buckets of the histogram. + bounds: list, + /// The count of each of the buckets. + bucket-counts: list, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The sum of the values recorded + sum: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// The histogram of all measurements of values from an instrument. + record exponential-histogram { + /// The individual aggregated measurements with unique attributes. + data-points: list, + /// When the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with an `exponential-histogram `. + record exponential-histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The maximum value recorded. + sum: metric-number, + /// Describes the resolution of the histogram. + /// + /// Boundaries are located at powers of the base, where: + /// + /// base = 2 ^ (2 ^ -scale) + scale: s8, + /// The number of values whose absolute value is less than or equal to + /// `zero_threshold`. + /// + /// When `zero_threshold` is `0`, this is the number of values that cannot be + /// expressed using the standard exponential formula as well as values that have + /// been rounded to zero. + zero-count: u64, + /// The range of positive value bucket counts. + positive-bucket: exponential-bucket, + /// The range of negative value bucket counts. + negative-bucket: exponential-bucket, + /// The width of the zero region. + /// + /// Where the zero region is defined as the closed interval + /// [-zero_threshold, zero_threshold]. + zero-threshold: f64, + /// The sampled exemplars collected during the time series. + exemplars: list, + } + + /// A set of bucket counts, encoded in a contiguous array of counts. + record exponential-bucket { + /// The bucket index of the first entry in the `counts` list. + offset: s32, + /// A list where `counts[i]` carries the count of the bucket at index `offset + i`. + /// + /// `counts[i]` is the count of values greater than base^(offset+i) and less than + /// or equal to base^(offset+i+1). + counts: list, + } + + /// A measurement sampled from a time series providing a typical example. + record exemplar { + /// The attributes recorded with the measurement but filtered out of the + /// time series' aggregated data. + filtered-attributes: list, + /// The time when the measurement was recorded. + time: datetime, + /// The measured value. + value: metric-number, + /// The ID of the span that was active during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + span-id: span-id, + /// The ID of the trace the active span belonged to during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + trace-id: trace-id, + } + + /// Defines the window that an aggregation was calculated over. + enum temporality { + /// A measurement interval that continues to expand forward in time from a + /// starting point. + /// + /// New measurements are added to all previous measurements since a start time. + /// + /// This is the default temporality. + cumulative, + /// A measurement interval that resets each cycle. + /// + /// Measurements from one cycle are recorded independently, measurements from + /// other cycles do not affect them. + delta, + /// Configures Synchronous Counter and Histogram instruments to use + /// Delta aggregation temporality, which allows them to shed memory + /// following a cardinality explosion, thus use less memory. + low-memory, + } + + /// The number types available for any given instrument. + variant metric-number { + %f64(f64), + %s64(s64), + %u64(u64), + } +} diff --git a/examples/otel-components/wit/overrides/wasi-otel/tracing.wit b/examples/otel-components/wit/overrides/wasi-otel/tracing.wit new file mode 100644 index 0000000..9d0f7ff --- /dev/null +++ b/examples/otel-components/wit/overrides/wasi-otel/tracing.wit @@ -0,0 +1,122 @@ +interface tracing { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use types.{key-value, instrumentation-scope}; + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + // Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } +} diff --git a/examples/otel-components/wit/overrides/wasi-otel/types.wit b/examples/otel-components/wit/overrides/wasi-otel/types.wit new file mode 100644 index 0000000..6fa87b5 --- /dev/null +++ b/examples/otel-components/wit/overrides/wasi-otel/types.wit @@ -0,0 +1,46 @@ +interface types { + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + /// + /// This corresponds with the `AnyValue` type defined in the [attribute spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue). + /// Because WIT doesn't support recursive types, the data needs to be serialized. JSON is used as the encoding format. + /// + /// Byte arrays require special encoding since JSON cannot distinguish them from number arrays. + /// They are base64-encoded with a prefix that follows the Data URI RFC 2397 convention: + /// `data:application/octet-stream;base64,` + type value = string; + + /// An immutable representation of the entity producing telemetry as attributes. + record %resource { + /// Attributes that identify the resource. + attributes: list, + /// The schema URL to be recorded in the emitted resource. + schema-url: option, + } + + /// Describes the instrumentation scope that produced telemetry. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + + /// The library version. + version: option, + + /// Schema URL used by this library. + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + schema-url: option, + + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} diff --git a/examples/otel-components/wit/overrides/wasi-otel/world.wit b/examples/otel-components/wit/overrides/wasi-otel/world.wit new file mode 100644 index 0000000..ec32b34 --- /dev/null +++ b/examples/otel-components/wit/overrides/wasi-otel/world.wit @@ -0,0 +1,9 @@ +/// patched to use 0.2.6 instead of 0.2.0 for wasi:clocks and wasi:io +package wasi:otel@0.2.0-rc.2+patch; + +world imports { + import types; + import tracing; + import metrics; + import logs; +} diff --git a/examples/otel/wkg.lock b/examples/otel-components/wkg.lock similarity index 100% rename from examples/otel/wkg.lock rename to examples/otel-components/wkg.lock diff --git a/examples/otel/wkg.toml b/examples/otel-components/wkg.toml similarity index 100% rename from examples/otel/wkg.toml rename to examples/otel-components/wkg.toml diff --git a/examples/otel-service/Cargo.lock b/examples/otel-service/Cargo.lock new file mode 100644 index 0000000..3385671 --- /dev/null +++ b/examples/otel-service/Cargo.lock @@ -0,0 +1,7303 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "gimli 0.33.1", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auditable-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5" +dependencies = [ + "semver", + "serde", + "serde_json", + "topological-sort", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[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 = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cap-fs-ext" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5528f85b1e134ae811704e41ef80930f56e795923f866813255bc342cc20654" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes", + "windows-sys 0.59.0", +] + +[[package]] +name = "cap-net-ext" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7" +dependencies = [ + "cap-primitives", + "cap-std", + "rustix 1.1.4", + "smallvec", +] + +[[package]] +name = "cap-primitives" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cf3aea8a5081171859ef57bc1606b1df6999df4f1110f8eef68b30098d1d3a" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix 1.1.4", + "rustix-linux-procfs", + "windows-sys 0.59.0", + "winx", +] + +[[package]] +name = "cap-rand" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8144c22e24bbcf26ade86cb6501a0916c46b7e4787abdb0045a467eb1645a1d" +dependencies = [ + "ambient-authority", + "rand 0.8.5", +] + +[[package]] +name = "cap-std" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6dc3090992a735d23219de5c204927163d922f42f575a0189b005c62d37549a" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix 1.1.4", +] + +[[package]] +name = "cap-time-ext" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def102506ce40c11710a9b16e614af0cde8e76ae51b1f48c04b8d79f4b671a80" +dependencies = [ + "ambient-authority", + "cap-primitives", + "iana-time-zone", + "once_cell", + "rustix 1.1.4", + "winx", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "composable-http-server" +version = "0.5.0-alpha.2" +dependencies = [ + "anyhow", + "composable-runtime", + "http-body-util", + "hyper", + "hyper-util", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "serde", + "serde_json", + "tokio", + "tracing", + "uuid", +] + +[[package]] +name = "composable-interceptor" +version = "0.5.0-alpha.2" +dependencies = [ + "anyhow", + "clap", + "tracing", + "tracing-subscriber", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", + "wat", + "wit-parser 0.245.1", +] + +[[package]] +name = "composable-otel" +version = "0.5.0-alpha.2" +dependencies = [ + "anyhow", + "composable-runtime", + "indexmap 2.13.0", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "serde", + "serde_json", + "tokio", + "tracing", + "wasmtime", +] + +[[package]] +name = "composable-runtime" +version = "0.5.0-alpha.2" +dependencies = [ + "anyhow", + "clap", + "composable-interceptor", + "http-body-util", + "hyper", + "oci-client", + "petgraph 0.8.3", + "rustyline", + "serde", + "serde_json", + "static-config", + "tokio", + "tokio-util", + "toml 1.1.0+spec-1.1.0", + "tracing", + "tracing-subscriber", + "uuid", + "wac-graph", + "wac-types", + "wasm-pkg-client", + "wasmtime", + "wasmtime-wasi", + "wasmtime-wasi-config", + "wasmtime-wasi-http", + "wasmtime-wasi-io", + "wit-component 0.245.1", + "wit-parser 0.245.1", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml 0.8.23", + "yaml-rust2", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.2", + "windows-sys 0.59.0", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-assembler-x64" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40630d663279bc855bff805d6f5e8a0b6a1867f9df95b010511ac6dc894e9395" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee6aec5ceb55e5fdbcf7ef677d7c7195531360ff181ce39b2b31df11d57305f" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a92d78cc3f087d7e7073828f08d98c7074a3a062b6b29a1b7783ce74305685e" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-bitset" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcc73d756f2e0d7eda6144fe64a2bc69c624de893cb1be51f1442aed77881d2" +dependencies = [ + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d94c2cd0d73b41369b88da1129589bc3a2d99cf49979af1d14751f35b7a1b" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli 0.33.1", + "hashbrown 0.15.5", + "libm", + "log", + "pulley-interpreter", + "regalloc2", + "rustc-hash", + "serde", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235da0e52ee3a0052d0e944c3470ff025b1f4234f6ec4089d3109f2d2ffa6cbd" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck 0.5.0", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c07c6c440bd1bf920ff7597a1e743ede1f68dcd400730bd6d389effa7662af" + +[[package]] +name = "cranelift-control" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8797c022e02521901e1aee483dea3ed3c67f2bf0a26405c9dd48e8ee7a70944b" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d8e72637246edd2cba337939850caa8b201f6315925ec4c156fdd089999699" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c31db0085c3dfa131e739c3b26f9f9c84d69a9459627aac1ac4ef8355e3411b" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524d804c1ebd8c542e6f64e71aa36934cec17c5da4a9ae3799796220317f5d23" + +[[package]] +name = "cranelift-native" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc9598f02540e382e1772416eba18e93c5275b746adbbf06ac1f3cf149415270" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.129.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d953932541249c91e3fa70a75ff1e52adc62979a2a8132145d4b9b3e6d1a9b6a" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn", +] + +[[package]] +name = "dbus" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b3aa68d7e7abee336255bd7248ea965cc393f3e70411135a6f6a4b651345d4" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "dbus-secret-service" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708b509edf7889e53d7efb0ffadd994cc6c2345ccb62f55cfd6b0682165e4fa6" +dependencies = [ + "aes", + "block-padding", + "cbc", + "dbus", + "fastrand", + "hkdf", + "num", + "once_cell", + "sha2", + "zeroize", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "docker_credential" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8" +dependencies = [ + "base64 0.21.7", + "serde", + "serde_json", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "etcetera" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96" +dependencies = [ + "cfg-if", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix 1.1.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs-set-times" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" +dependencies = [ + "io-lifetimes", + "rustix 1.1.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "fxprof-processed-profile" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25234f20a3ec0a962a61770cfe39ecf03cb529a6e474ad8cff025ed497eda557" +dependencies = [ + "bitflags", + "debugid", + "rustc-hash", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "getset" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e16c5073773ccf057c282be832a59ee53ef5ff98db3aeff7f8314f52ffc196" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap 2.13.0", + "stable_deref_trait", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "guest" +version = "0.1.0" +dependencies = [ + "wit-bindgen 0.53.1", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "host" +version = "0.1.0" +dependencies = [ + "anyhow", + "composable-http-server", + "composable-otel", + "composable-runtime", + "tokio", + "tracing-subscriber", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-auth" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "150fa4a9462ef926824cf4519c84ed652ca8f4fbae34cb8af045b5cbcaf98822" +dependencies = [ + "memchr", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls 0.23.37", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.4", + "tower-service", + "webpki-roots 1.0.6", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "io-extras" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2285ddfe3054097ef4b2fe909ef8c3bcd1ea52a8f0d274416caebeef39f04a65" +dependencies = [ + "io-lifetimes", + "windows-sys 0.59.0", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06432fb54d3be7964ecd3649233cddf80db2832f47fec34c01f65b3d9d774983" + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "java-properties" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf6f484471c451f2b51eabd9e66b3fa7274550c5ec4b6c3d6070840945117f" +dependencies = [ + "encoding_rs", + "lazy_static 1.5.0", + "regex", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "jsonwebtoken" +version = "10.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" +dependencies = [ + "base64 0.22.1", + "getrandom 0.2.17", + "js-sys", + "serde", + "serde_json", + "signature", +] + +[[package]] +name = "keyring" +version = "3.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" +dependencies = [ + "byteorder", + "dbus-secret-service", + "linux-keyutils", + "log", + "secret-service", + "security-framework 2.11.1", + "security-framework 3.7.0", + "windows-sys 0.60.2", + "zbus", + "zeroize", +] + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "libc", +] + +[[package]] +name = "linux-keyutils" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83270a18e9f90d0707c41e9f35efada77b64c0e6f3f1810e71c8368a864d5590" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "logos" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" +dependencies = [ + "beef", + "fnv", + "lazy_static 1.5.0", + "proc-macro2", + "quote", + "regex-syntax", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix 1.1.4", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "miette-derive", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normpath" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "crc32fast", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "memchr", +] + +[[package]] +name = "oci-client" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b7f8deaffcd3b0e3baf93dddcab3d18b91d46dc37d38a8b170089b234de5bb3" +dependencies = [ + "bytes", + "chrono", + "futures-util", + "http", + "http-auth", + "jsonwebtoken", + "lazy_static 1.5.0", + "oci-spec", + "olpc-cjson", + "regex", + "reqwest 0.13.2", + "serde", + "serde_json", + "sha2", + "thiserror 2.0.18", + "tokio", + "tracing", + "unicase", +] + +[[package]] +name = "oci-spec" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8445a2631507cec628a15fdd6154b54a3ab3f20ed4fe9d73a3b8b7a4e1ba03a" +dependencies = [ + "const_format", + "derive_builder", + "getset", + "regex", + "serde", + "serde_json", + "strum", + "strum_macros", + "thiserror 2.0.18", +] + +[[package]] +name = "oci-wasm" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841cceed413ad8a4c8b4a833ccfa333eebe55dfb12af7c3899687258934ca2a4" +dependencies = [ + "anyhow", + "chrono", + "oci-client", + "serde", + "serde_json", + "sha2", + "tokio", + "wit-component 0.244.0", + "wit-parser 0.244.0", +] + +[[package]] +name = "olpc-cjson" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696183c9b5fe81a7715d074fd632e8bd46f4ccc0231a3ed7fc580a80de5f7083" +dependencies = [ + "serde", + "serde_json", + "unicode-normalization", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "opentelemetry" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry", + "reqwest 0.12.28", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +dependencies = [ + "http", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost 0.14.3", + "reqwest 0.12.28", + "thiserror 2.0.18", + "tokio", + "tonic", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost 0.14.3", + "tonic", + "tonic-prost", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand 0.9.2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pbjson" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" +dependencies = [ + "base64 0.21.7", + "serde", +] + +[[package]] +name = "pbjson-build" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" +dependencies = [ + "heck 0.4.1", + "itertools 0.11.0", + "prost 0.12.6", + "prost-types", +] + +[[package]] +name = "pbjson-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f596653ba4ac51bdecbb4ef6773bc7f56042dc13927910de1684ad3d32aa12" +dependencies = [ + "bytes", + "chrono", + "pbjson", + "pbjson-build", + "prost 0.12.6", + "prost-build", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap 2.13.0", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "serde", +] + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.8+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap", + "once_cell", + "petgraph 0.6.5", + "prettyplease", + "prost 0.12.6", + "prost-types", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-reflect" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5eec97d5d34bdd17ad2db2219aabf46b054c6c41bd5529767c9ce55be5898f" +dependencies = [ + "logos", + "miette", + "once_cell", + "prost 0.12.6", + "prost-types", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "protox" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac532509cee918d40f38c3e12f8ef9230f215f017d54de7dd975015538a42ce7" +dependencies = [ + "bytes", + "miette", + "prost 0.12.6", + "prost-reflect", + "prost-types", + "protox-parse", + "thiserror 1.0.69", +] + +[[package]] +name = "protox-parse" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6c33f43516fe397e2f930779d720ca12cd057f7da4cd6326a0ef78d69dee96" +dependencies = [ + "logos", + "miette", + "prost-types", + "thiserror 1.0.69", +] + +[[package]] +name = "ptree" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "289cfd20ebec0e7ff2572e370dd7a1c9973ba666d3c38c5e747de0a4ada21f17" +dependencies = [ + "anstyle", + "config", + "directories", + "petgraph 0.6.5", + "serde", + "serde-value", + "tint", +] + +[[package]] +name = "pulley-interpreter" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc2d61e068654529dc196437f8df0981db93687fdc67dec6a5de92363120b9da" +dependencies = [ + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-core", +] + +[[package]] +name = "pulley-macros" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f210c61b6ecfaebbba806b6d9113a222519d4e5cc4ab2d5ecca047bb7927ae" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.37", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls 0.23.37", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regalloc2" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.15.5", + "log", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.37", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "webpki-roots 1.0.6", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.37", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "rust-ini" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustix-linux-procfs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" +dependencies = [ + "once_cell", + "rustix 1.1.4", +] + +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "aws-lc-rs", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.103.10", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.37", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.10", + "security-framework 3.7.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rustyline" +version = "17.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e902948a25149d50edc1a8e0141aad50f54e22ba83ff988cf8f7c9ef07f50564" +dependencies = [ + "bitflags", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix 0.30.1", + "radix_trie", + "unicode-segmentation", + "unicode-width 0.2.2", + "utf8parse", + "windows-sys 0.60.2", +] + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "secret-service" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4d35ad99a181be0a60ffcbe85d680d98f87bdc4d7644ade319b87076b9dbfd4" +dependencies = [ + "aes", + "cbc", + "futures-util", + "generic-array", + "hkdf", + "num", + "once_cell", + "rand 0.8.5", + "serde", + "sha2", + "zbus", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.13.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha256" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", + "tokio", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static 1.5.0", +] + +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spdx" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3" +dependencies = [ + "smallvec", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static-config" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f175a5b5332529bd2b7379e2f74edc831ad06e36a26c3b294d6a932c83cc0b" +dependencies = [ + "anyhow", + "clap", + "java-properties", + "serde", + "walrus", + "wasm-compose 0.240.0", + "wasm-metadata 0.240.0", + "wit-component 0.240.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-interface" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4592f674ce18521c2a81483873a49596655b179f71c5e05d10c1fe66c78745" +dependencies = [ + "bitflags", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes", + "rustix 0.38.44", + "windows-sys 0.59.0", + "winx", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tint" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7af24570664a3074673dbbf69a65bdae0ae0b72f2949b1adfbacb736ee4d6896" +dependencies = [ + "lazy_static 0.2.11", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls 0.23.37", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap 2.13.0", + "serde_core", + "serde_spanned 1.1.0", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" +dependencies = [ + "indexmap 2.13.0", + "serde_core", + "serde_spanned 1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.1", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.13.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.8+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" +dependencies = [ + "indexmap 2.13.0", + "toml_datetime 1.1.0+spec-1.1.0", + "toml_parser", + "winnow 1.0.1", +] + +[[package]] +name = "toml_parser" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" + +[[package]] +name = "tonic" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + +[[package]] +name = "topological-sort" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 2.13.0", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "getrandom 0.4.2", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wac-graph" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c22d99cf996435bda507f323cca418cd513c3c604ca3157f5e4e79990b47378" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "petgraph 0.6.5", + "semver", + "thiserror 1.0.69", + "wac-types", + "wasm-encoder 0.244.0", + "wasm-metadata 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "wac-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86d6f994ea751789cd416144648039ee9bdb385dffb6d890bd51a90e2f50778" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "semver", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "walrus" +version = "0.24.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a1ca30ceb782a7f4524722a7ee27bd6c4bcde97d48802ba270fd69ff1a954" +dependencies = [ + "anyhow", + "gimli 0.26.2", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasm-encoder 0.240.0", + "wasmparser 0.240.0", +] + +[[package]] +name = "walrus-macro" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef06db404cbaed87cb25fd2ca3a62502af485f43383c9641ffcf1479d02fffd" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "warg-api" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98505d42b5289563c6d659f625b6789a97980166508bd00862c4328bf41c261" +dependencies = [ + "indexmap 2.13.0", + "itertools 0.12.1", + "serde", + "serde_with", + "thiserror 1.0.69", + "warg-crypto", + "warg-protocol", +] + +[[package]] +name = "warg-client" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738a33cf369dea5d2684a61a7035c038858f40fc090d4981d35ee3fab416ddb8" +dependencies = [ + "anyhow", + "async-recursion", + "async-trait", + "bytes", + "clap", + "dialoguer", + "dirs", + "futures-util", + "indexmap 2.13.0", + "itertools 0.12.1", + "keyring", + "libc", + "normpath", + "once_cell", + "pathdiff", + "ptree", + "reqwest 0.12.28", + "secrecy", + "semver", + "serde", + "serde_json", + "sha256", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "tracing", + "url", + "walkdir", + "warg-api", + "warg-crypto", + "warg-protocol", + "warg-transparency", + "wasm-compose 0.5.5", + "wasm-encoder 0.41.2", + "wasmparser 0.121.2", + "wasmprinter 0.2.80", + "windows-sys 0.52.0", +] + +[[package]] +name = "warg-crypto" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71661a52504e20b9ec8e9846bddda041f30eb7aedeb6888c057d6a213eaedf87" +dependencies = [ + "anyhow", + "base64 0.21.7", + "digest", + "hex", + "leb128", + "once_cell", + "p256", + "rand_core 0.6.4", + "secrecy", + "serde", + "sha2", + "signature", + "thiserror 1.0.69", +] + +[[package]] +name = "warg-protobuf" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af0b1733deeb4f0c496d2b8e3ddb0e93b39da19d90c4f6d7594f2861f7e3086" +dependencies = [ + "anyhow", + "pbjson", + "pbjson-build", + "pbjson-types", + "prost 0.12.6", + "prost-build", + "prost-types", + "protox", + "regex", + "serde", + "warg-crypto", +] + +[[package]] +name = "warg-protocol" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "922504990dbb7297c67139140fc5c08f596988fcbaf38d9e7d3bf89a0c0759fe" +dependencies = [ + "anyhow", + "base64 0.21.7", + "hex", + "indexmap 2.13.0", + "pbjson-types", + "prost 0.12.6", + "prost-types", + "semver", + "serde", + "serde_with", + "thiserror 1.0.69", + "warg-crypto", + "warg-protobuf", + "warg-transparency", + "wasmparser 0.121.2", +] + +[[package]] +name = "warg-transparency" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8d8110b6800c43422676201a6a62167769b015ca29a8fcab67d789ac8b9c63" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "prost 0.12.6", + "thiserror 1.0.69", + "warg-crypto", + "warg-protobuf", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-compose" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd324927af875ebedb1b820c00e3c585992d33c2c787c5021fe6d8982527359b" +dependencies = [ + "anyhow", + "heck 0.4.1", + "im-rc", + "indexmap 2.13.0", + "log", + "petgraph 0.6.5", + "serde", + "serde_derive", + "serde_yaml", + "smallvec", + "wasm-encoder 0.41.2", + "wasmparser 0.121.2", + "wat", +] + +[[package]] +name = "wasm-compose" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feeb9a231e63bd5d5dfe07e9f8daa53d5c85e4f7de5ef756d3b4e6a5f501c578" +dependencies = [ + "anyhow", + "heck 0.4.1", + "im-rc", + "indexmap 2.13.0", + "log", + "petgraph 0.6.5", + "serde", + "serde_derive", + "serde_yaml", + "smallvec", + "wasm-encoder 0.240.0", + "wasmparser 0.240.0", + "wat", +] + +[[package]] +name = "wasm-compose" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92cda9c76ca8dcac01a8b497860c2cb15cd6f216dc07060517df5abbe82512ac" +dependencies = [ + "anyhow", + "heck 0.5.0", + "im-rc", + "indexmap 2.13.0", + "log", + "petgraph 0.6.5", + "serde", + "serde_derive", + "serde_yaml", + "smallvec", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", + "wat", +] + +[[package]] +name = "wasm-encoder" +version = "0.41.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "972f97a5d8318f908dded23594188a90bcd09365986b1163e66d70170e5287ae" +dependencies = [ + "leb128", + "wasmparser 0.121.2", +] + +[[package]] +name = "wasm-encoder" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f" +dependencies = [ + "leb128fmt", + "wasmparser 0.240.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" +dependencies = [ + "leb128fmt", + "wasmparser 0.245.1", +] + +[[package]] +name = "wasm-metadata" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee093e1e1ccffa005b9b778f7a10ccfd58e25a20eccad294a1a93168d076befb" +dependencies = [ + "anyhow", + "auditable-serde", + "flate2", + "indexmap 2.13.0", + "serde", + "serde_derive", + "serde_json", + "spdx", + "url", + "wasm-encoder 0.240.0", + "wasmparser 0.240.0", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "auditable-serde", + "flate2", + "indexmap 2.13.0", + "serde", + "serde_derive", + "serde_json", + "spdx", + "url", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-metadata" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder 0.245.1", + "wasmparser 0.245.1", +] + +[[package]] +name = "wasm-pkg-client" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f75b3d2d7271cbbc462f9cdf4374504ea6daddb969819bb0d4325aa5db3c15c" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.22.1", + "bytes", + "docker_credential", + "etcetera", + "futures-util", + "oci-client", + "oci-wasm", + "reqwest 0.12.28", + "secrecy", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "toml 0.8.23", + "tracing", + "tracing-subscriber", + "url", + "warg-client", + "warg-crypto", + "warg-protocol", + "wasm-metadata 0.244.0", + "wasm-pkg-common", + "wit-component 0.244.0", +] + +[[package]] +name = "wasm-pkg-common" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef7ac86a15665be835091dfc4ed2db9e30d9e0b8461ba8bf8fccea4f1ea10541" +dependencies = [ + "anyhow", + "bytes", + "etcetera", + "futures-util", + "http", + "semver", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", + "tokio", + "toml 0.8.23", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.121.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" +dependencies = [ + "bitflags", + "indexmap 2.13.0", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" +dependencies = [ + "bitflags", + "hashbrown 0.16.1", + "indexmap 2.13.0", + "semver", + "serde", +] + +[[package]] +name = "wasmprinter" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e73986a6b7fdfedb7c5bf9e7eb71135486507c8fbc4c0c42cffcb6532988b7" +dependencies = [ + "anyhow", + "wasmparser 0.121.2", +] + +[[package]] +name = "wasmprinter" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09390d7b2bd7b938e563e4bff10aa345ef2e27a3bc99135697514ef54495e68f" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasmtime" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39bef52be4fb4c5b47d36f847172e896bc94b35c9c6a6f07117686bd16ed89a7" +dependencies = [ + "addr2line", + "async-trait", + "bitflags", + "bumpalo", + "cc", + "cfg-if", + "encoding_rs", + "futures", + "fxprof-processed-profile", + "gimli 0.33.1", + "ittapi", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rayon", + "rustix 1.1.4", + "semver", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "target-lexicon", + "tempfile", + "wasm-compose 0.244.0", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", + "wasmtime-environ", + "wasmtime-internal-cache", + "wasmtime-internal-component-macro", + "wasmtime-internal-component-util", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "wasmtime-internal-winch", + "wat", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-environ" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb637d5aa960ac391ca5a4cbf3e45807632e56beceeeb530e14dfa67fdfccc62" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-bitset", + "cranelift-entity", + "gimli 0.33.1", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "log", + "object", + "postcard", + "rustc-demangle", + "semver", + "serde", + "serde_derive", + "smallvec", + "target-lexicon", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", + "wasmprinter 0.244.0", + "wasmtime-internal-component-util", + "wasmtime-internal-core", +] + +[[package]] +name = "wasmtime-internal-cache" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ab6c428c610ae3e7acd25ca2681b4d23672c50d8769240d9dda99b751d4deec" +dependencies = [ + "base64 0.22.1", + "directories-next", + "log", + "postcard", + "rustix 1.1.4", + "serde", + "serde_derive", + "sha2", + "toml 0.9.12+spec-1.1.0", + "wasmtime-environ", + "windows-sys 0.61.2", + "zstd", +] + +[[package]] +name = "wasmtime-internal-component-macro" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca768b11d5e7de017e8c3d4d444da6b4ce3906f565bcbc253d76b4ecbb5d2869" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn", + "wasmtime-internal-component-util", + "wasmtime-internal-wit-bindgen", + "wit-parser 0.244.0", +] + +[[package]] +name = "wasmtime-internal-component-util" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763f504faf96c9b409051e96a1434655eea7f56a90bed9cb1e22e22c941253fd" + +[[package]] +name = "wasmtime-internal-core" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a4a3f055a804a2f3d86e816a9df78a8fa57762212a8506164959224a40cd48" +dependencies = [ + "anyhow", + "libm", +] + +[[package]] +name = "wasmtime-internal-cranelift" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55154a91d22ad51f9551124ce7fb49ddddc6a82c4910813db4c790c97c9ccf32" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli 0.33.1", + "itertools 0.14.0", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.18", + "wasmparser 0.244.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-fiber" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05decfad1021ad2efcca5c1be9855acb54b6ee7158ac4467119b30b7481508e3" +dependencies = [ + "cc", + "cfg-if", + "libc", + "rustix 1.1.4", + "wasmtime-environ", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-jit-debug" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924980c50427885fd4feed2049b88380178e567768aaabf29045b02eb262eaa7" +dependencies = [ + "cc", + "object", + "rustix 1.1.4", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57d24e8d1334a0e5a8b600286ffefa1fc4c3e8176b110dff6fbc1f43c4a599b" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-unwinder" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a1a144bd4393593a868ba9df09f34a6a360cb5db6e71815f20d3f649c6e6735" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "log", + "object", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-internal-versioned-export-macros" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a6948b56bb00c62dbd205ea18a4f1ceccbe1e4b8479651fdb0bab2553790f20" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "wasmtime-internal-winch" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9130b3ab6fb01be80b27b9a2c84817af29ae8224094f2503d2afa9fea5bf9d00" +dependencies = [ + "cranelift-codegen", + "gimli 0.33.1", + "log", + "object", + "target-lexicon", + "wasmparser 0.244.0", + "wasmtime-environ", + "wasmtime-internal-cranelift", + "winch-codegen", +] + +[[package]] +name = "wasmtime-internal-wit-bindgen" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102d0d70dbfede00e4cc9c24e86df6d32c03bf6f5ad06b5d6c76b0a4a5004c4a" +dependencies = [ + "anyhow", + "bitflags", + "heck 0.5.0", + "indexmap 2.13.0", + "wit-parser 0.244.0", +] + +[[package]] +name = "wasmtime-wasi" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea938f6f4f11e5ffe6d8b6f34c9a994821db9511c3e9c98e535896f27d06bb92" +dependencies = [ + "async-trait", + "bitflags", + "bytes", + "cap-fs-ext", + "cap-net-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "futures", + "io-extras", + "io-lifetimes", + "rustix 1.1.4", + "system-interface", + "thiserror 2.0.18", + "tokio", + "tracing", + "url", + "wasmtime", + "wasmtime-wasi-io", + "wiggle", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-wasi-config" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4098f2946fa6a62adc001554f5f4039a3c7f8e46738bf89a3279cdf9ef650cc" +dependencies = [ + "wasmtime", +] + +[[package]] +name = "wasmtime-wasi-http" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fdc8d790eb6505a911489b72671de8d84330b621329283e34f2a46d15c3e6dd" +dependencies = [ + "async-trait", + "bytes", + "futures", + "http", + "http-body", + "http-body-util", + "hyper", + "rustls 0.22.4", + "tokio", + "tokio-rustls 0.25.0", + "tracing", + "wasmtime", + "wasmtime-wasi", + "wasmtime-wasi-io", + "webpki-roots 0.26.11", +] + +[[package]] +name = "wasmtime-wasi-io" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71cb16a88d0443b509d6eca4298617233265179090abf03e0a8042b9b251e9da" +dependencies = [ + "async-trait", + "bytes", + "futures", + "tracing", + "wasmtime", +] + +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + +[[package]] +name = "wast" +version = "245.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cf1149285569120b8ce39db8b465e8a2b55c34cbb586bd977e43e2bc7300bf" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width 0.2.2", + "wasm-encoder 0.245.1", +] + +[[package]] +name = "wat" +version = "1.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd48d1679b6858988cb96b154dda0ec5bbb09275b71db46057be37332d5477be" +dependencies = [ + "wast 245.0.1", +] + +[[package]] +name = "web-sys" +version = "0.3.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.6", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "wiggle" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dca2bf96d20f0c70e6741cc6c8c1a9ee4c3c0310c7ad1971242628c083cc9a5" +dependencies = [ + "bitflags", + "thiserror 2.0.18", + "tracing", + "wasmtime", + "wasmtime-environ", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d8c016d6d3ec6dc6b8c80c23cede4ee2386ccf347d01984f7991d7659f73ef" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn", + "wasmtime-environ", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a267096e48857096f035fffca29e22f0bbe840af4d74a6725eb695e1782110" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wiggle-generate", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winch-codegen" +version = "42.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1977857998e4dd70d26e2bfc0618a9684a2fb65b1eca174dc13f3b3e9c2159ca" +dependencies = [ + "cranelift-assembler-x64", + "cranelift-codegen", + "gimli 0.33.1", + "regalloc2", + "smallvec", + "target-lexicon", + "thiserror 2.0.18", + "wasmparser 0.244.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "winx" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d" +dependencies = [ + "bitflags", + "windows-sys 0.59.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro 0.51.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e915216dde3e818093168df8380a64fba25df468d626c80dd5d6a184c87e7c7" +dependencies = [ + "bitflags", + "wit-bindgen-rust-macro 0.53.1", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser 0.244.0", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser 0.245.1", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn", + "wasm-metadata 0.244.0", + "wit-bindgen-core 0.51.0", + "wit-component 0.244.0", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "863a7ab3c4dfee58db196811caeb0718b88412a0aef3d1c2b02fcbae1e37c688" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn", + "wasm-metadata 0.245.1", + "wit-bindgen-core 0.53.1", + "wit-component 0.245.1", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core 0.51.0", + "wit-bindgen-rust 0.51.0", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d14f3a9bfa3804bb0e9ab7f66da047f210eded6a1297ae3ba5805b384d64797f" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core 0.53.1", + "wit-bindgen-rust 0.53.1", +] + +[[package]] +name = "wit-component" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dc5474b078addc5fe8a72736de8da3acfb3ff324c2491133f8b59594afa1a20" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.240.0", + "wasm-metadata 0.240.0", + "wasmparser 0.240.0", + "wit-parser 0.240.0", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.244.0", + "wasm-metadata 0.244.0", + "wasmparser 0.244.0", + "wit-parser 0.244.0", +] + +[[package]] +name = "wit-component" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.245.1", + "wasm-metadata 0.245.1", + "wasmparser 0.245.1", + "wit-parser 0.245.1", +] + +[[package]] +name = "wit-parser" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9875ea3fa272f57cc1fc50f225a7b94021a7878c484b33792bccad0d93223439" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.240.0", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.244.0", +] + +[[package]] +name = "wit-parser" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929" +dependencies = [ + "anyhow", + "hashbrown 0.16.1", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.245.1", +] + +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror 1.0.69", + "wast 35.0.2", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "yaml-rust2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.29.0", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/examples/otel-service/Cargo.toml b/examples/otel-service/Cargo.toml new file mode 100644 index 0000000..02ccabc --- /dev/null +++ b/examples/otel-service/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["guest", "host"] +resolver = "3" diff --git a/examples/otel-service/README.md b/examples/otel-service/README.md new file mode 100644 index 0000000..56e38f6 --- /dev/null +++ b/examples/otel-service/README.md @@ -0,0 +1,135 @@ +# OpenTelemetry Example using OtelService + +This example demonstrates end-to-end OpenTelemetry trace propagation using the built-in `otel` capability (from the [composable-otel](../../crates/opentelemetry) sub-crate) and the built-in `http` server (from the [composable-http-server](../../crates/http-server) sub-crate). + +An HTTP request arrives with (or without) a `traceparent` header. `HttpService` opens a server span and writes the resulting `traceparent` into the invocation's propagation context. The `otel` capability surfaces that traceparent to the guest through `outer-span-context` on the `wasi:otel/tracing` interface, and the guest emits a child span and log record. `HttpService` and `OtelService` each own their own OTLP exporter. + +## Flow + +``` + HTTP client + | (optional: traceparent header) + v + HttpService --- (server span, OTLP exporter) -----------. + | opens server span | + | adds traceparent to invocation context v + v OTLP collector + guest (component) (external) + outer-span-context() --> otel capability ^ + child span + log --> otel capability | + | | + v | + OtelService ---------' + (OTLP exporter) +``` + +- **HttpService:** Accepts requests on `/test`, extracts the inbound `traceparent` (if any), opens a server span, and writes the span's traceparent into the invocation's propagation context. Exports its server span via its own OTLP pipeline (configured by `otlp-endpoint` on `[server.http]`). +- **otel capability:** Reads the traceparent from the propagation context and returns it to the guest from `outer-span-context`. Forwards guest spans and log records emitted through `wasi:otel` to the `OtelService` exporter. +- **guest:** Calls `outer-span-context` to read the propagated trace id and parent span id, opens its own child span, emits a log record, and ends the span. +- **OtelService:** Owns an independent OTLP pipeline (configured by `[capability.otel]`). Exports guest spans and logs forwarded by the `otel` capability. + +## Host Binary + +The host registers the two services when building the runtime: + +```rust +let runtime = Runtime::builder() + .from_path(std::path::PathBuf::from("config.toml")) + .with_service::() + .with_service::() + .build() + .await?; + +runtime.run().await +``` + +Each `Service` implementation registered via `with_service` may contribute config handlers, capability factories, and lifecycle hooks. + +## Configuration + +```toml +[capability.otel] +type = "otel" +endpoint = "http://localhost:4317" +protocol = "grpc" + +[capability.otel.resource] +"service.name" = "otel-service-example" +"service.version" = "0.1.0" + +[server.http] +type = "http" +port = 8080 +otlp-endpoint = "http://localhost:4317" + +[server.http.route.test] +path = "/test" +component = "guest" +function = "run" + +[component.guest] +uri = "./target/wasm32-unknown-unknown/release/guest.wasm" +imports = ["otel", "clocks", "random"] + +[capability.clocks] +type = "wasi:clocks" + +[capability.random] +type = "wasi:random" +``` + +- `[capability.otel]`: configures the OTLP exporter (endpoint, protocol, resource attributes), and exports `wasi:otel/logs` and `wasi:otel/tracing` for guest components. +- `[server.http]`: runs the HTTP server on port 8080. `otlp-endpoint` configures `HttpService`'s own OTLP exporter for server spans (using the same endpoint URL as `OtelService`). +- `[server.http.route.test]`: dispatches `GET /test` to the guest's `run` function. + +## Guest Component + +The guest reads the propagated trace context, then creates a child span under it: + +```rust +let outer = tracing::outer_span_context(); + +let span_context = tracing::SpanContext { + trace_id: outer.trace_id.clone(), + span_id: /* freshly generated */, + trace_flags: tracing::TraceFlags::SAMPLED, + is_remote: false, + trace_state: vec![], +}; +tracing::on_start(&span_context); + +// ... emit log with trace_id / span_id from outer ... + +tracing::on_end(&tracing::SpanData { + span_context: span_context.clone(), + parent_span_id: outer.span_id.clone(), + // ... +}); +``` + +`outer-span-context` returns the span context the host opened for this invocation. If the inbound HTTP request included a `traceparent`, that trace id flows all the way down to the guest span. + +## Building and Running + +Prerequisite: an OTLP collector at `localhost:4317`. + +```bash +./build.sh # builds the guest wasm + host binary +./run.sh # starts the host on :8080 +``` + +In another terminal: + +```bash +./curl.sh +``` + +This sends two requests: + +1. `GET /test` with no traceparent: the host creates a root trace. +2. `GET /test` with a traceparent header: the host span becomes a child of that remote parent, and the guest span is a child of the host span. + +At the collector you should see, for each request: +- An HTTP server span (from `HttpService`). +- A guest span named `otel-service-example` whose `parent_span_id` is the server span's id. +- A log record correlated to the guest span via `trace_id` / `span_id`. diff --git a/examples/otel-service/build.sh b/examples/otel-service/build.sh new file mode 100755 index 0000000..5941101 --- /dev/null +++ b/examples/otel-service/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +wkg wit fetch + +cargo component build -p guest --target wasm32-unknown-unknown --release + +cargo build -p host --release diff --git a/examples/otel-service/config.toml b/examples/otel-service/config.toml new file mode 100644 index 0000000..be6f06b --- /dev/null +++ b/examples/otel-service/config.toml @@ -0,0 +1,28 @@ +[capability.otel] +type = "otel" +endpoint = "http://localhost:4317" +protocol = "grpc" + +[capability.otel.resource] +"service.name" = "otel-capability-example" +"service.version" = "0.1.0" + +[server.http] +type = "http" +port = 8080 +otlp-endpoint = "http://localhost:4317" + +[server.http.route.test] +path = "/test" +component = "guest" +function = "run" + +[component.guest] +uri = "./target/wasm32-unknown-unknown/release/guest.wasm" +imports = ["otel", "clocks", "random"] + +[capability.clocks] +type = "wasi:clocks" + +[capability.random] +type = "wasi:random" diff --git a/examples/otel-service/curl.sh b/examples/otel-service/curl.sh new file mode 100755 index 0000000..196b6dc --- /dev/null +++ b/examples/otel-service/curl.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "=== no traceparent (host generates root trace) ===" +curl http://localhost:8080/test + +echo "" +echo "=== traceparent (upstream parent of host span) ===" +curl -H "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" http://localhost:8080/test diff --git a/examples/otel-service/guest/Cargo.toml b/examples/otel-service/guest/Cargo.toml new file mode 100644 index 0000000..6e45f68 --- /dev/null +++ b/examples/otel-service/guest/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "guest" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wit-bindgen = "0.53.1" diff --git a/examples/otel-service/guest/src/lib.rs b/examples/otel-service/guest/src/lib.rs new file mode 100644 index 0000000..e268851 --- /dev/null +++ b/examples/otel-service/guest/src/lib.rs @@ -0,0 +1,86 @@ +wit_bindgen::generate!({ + path: "../wit", + world: "guest", + generate_all, +}); + +use wasi::otel::{logs, tracing}; + +struct Component; + +impl Guest for Component { + fn run() -> Result<(), String> { + // Get the host's current span context (propagated from incoming request headers). + let outer = tracing::outer_span_context(); + + // Start a guest span as a child of the host's span. + let now = wasi::clocks::wall_clock::now(); + let span_id = wasi::random::random::get_random_bytes(8) + .iter() + .map(|b| format!("{b:02x}")) + .collect::(); + let span_context = tracing::SpanContext { + trace_id: outer.trace_id.clone(), + span_id, + trace_flags: tracing::TraceFlags::SAMPLED, + is_remote: false, + trace_state: vec![], + }; + tracing::on_start(&span_context); + + // Emit a log record with no resource (routes through the default batch processor). + logs::on_emit(&logs::LogRecord { + timestamp: Some(now), + observed_timestamp: None, + severity_text: Some("INFO".to_string()), + severity_number: Some(9), + body: Some("otel-service example ran".to_string()), + attributes: Some(vec![logs::KeyValue { + key: "component".to_string(), + value: "otel-service-guest".to_string(), + }]), + event_name: None, + resource: None, + instrumentation_scope: Some(logs::InstrumentationScope { + name: "otel-service-example".to_string(), + version: Some("0.1.0".to_string()), + schema_url: None, + attributes: vec![], + }), + trace_id: Some(outer.trace_id.clone()), + span_id: Some(outer.span_id.clone()), + trace_flags: None, + }); + + // End the guest span. + let end_time = wasi::clocks::wall_clock::now(); + tracing::on_end(&tracing::SpanData { + span_context: span_context.clone(), + parent_span_id: outer.span_id.clone(), + span_kind: tracing::SpanKind::Internal, + name: "otel-service-example".to_string(), + start_time: now, + end_time, + attributes: vec![tracing::KeyValue { + key: "example".to_string(), + value: "otel-service".to_string(), + }], + events: vec![], + links: vec![], + status: tracing::Status::Ok, + instrumentation_scope: wasi::otel::types::InstrumentationScope { + name: "otel-service-example".to_string(), + version: Some("0.1.0".to_string()), + schema_url: None, + attributes: vec![], + }, + dropped_attributes: 0, + dropped_events: 0, + dropped_links: 0, + }); + + Ok(()) + } +} + +export!(Component); diff --git a/examples/otel-service/host/Cargo.toml b/examples/otel-service/host/Cargo.toml new file mode 100644 index 0000000..fb8abfb --- /dev/null +++ b/examples/otel-service/host/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "host" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1" +composable-http-server = { path = "../../../crates/http-server", default-features = false } +composable-otel = { path = "../../../crates/opentelemetry" } +composable-runtime = { path = "../../.." } +tokio = { version = "1", features = ["full"] } +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/examples/otel-service/host/src/main.rs b/examples/otel-service/host/src/main.rs new file mode 100644 index 0000000..b278932 --- /dev/null +++ b/examples/otel-service/host/src/main.rs @@ -0,0 +1,24 @@ +use anyhow::Result; +use composable_http_server::HttpService; +use composable_otel::OtelService; +use composable_runtime::Runtime; +use tracing_subscriber::EnvFilter; + +#[tokio::main] +async fn main() -> Result<()> { + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), + ) + .try_init() + .ok(); + + let runtime = Runtime::builder() + .from_path(std::path::PathBuf::from("config.toml")) + .with_service::() + .with_service::() + .build() + .await?; + + runtime.run().await +} diff --git a/examples/otel-service/run.sh b/examples/otel-service/run.sh new file mode 100755 index 0000000..21d1668 --- /dev/null +++ b/examples/otel-service/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -e + +cargo run -p host --release diff --git a/examples/otel-service/wit/deps/wasi-clocks-0.2.6/package.wit b/examples/otel-service/wit/deps/wasi-clocks-0.2.6/package.wit new file mode 100644 index 0000000..d638f1a --- /dev/null +++ b/examples/otel-service/wit/deps/wasi-clocks-0.2.6/package.wit @@ -0,0 +1,157 @@ +package wasi:clocks@0.2.6; + +/// WASI Monotonic Clock is a clock API intended to let users measure elapsed +/// time. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A monotonic clock is a clock which has an unspecified initial value, and +/// successive reads of the clock will produce non-decreasing values. +@since(version = 0.2.0) +interface monotonic-clock { + @since(version = 0.2.0) + use wasi:io/poll@0.2.6.{pollable}; + + /// An instant in time, in nanoseconds. An instant is relative to an + /// unspecified initial value, and can only be compared to instances from + /// the same monotonic-clock. + @since(version = 0.2.0) + type instant = u64; + + /// A duration of time, in nanoseconds. + @since(version = 0.2.0) + type duration = u64; + + /// Read the current value of the clock. + /// + /// The clock is monotonic, therefore calling this function repeatedly will + /// produce a sequence of non-decreasing values. + @since(version = 0.2.0) + now: func() -> instant; + + /// Query the resolution of the clock. Returns the duration of time + /// corresponding to a clock tick. + @since(version = 0.2.0) + resolution: func() -> duration; + + /// Create a `pollable` which will resolve once the specified instant + /// has occurred. + @since(version = 0.2.0) + subscribe-instant: func(when: instant) -> pollable; + + /// Create a `pollable` that will resolve after the specified duration has + /// elapsed from the time this function is invoked. + @since(version = 0.2.0) + subscribe-duration: func(when: duration) -> pollable; +} + +/// WASI Wall Clock is a clock API intended to let users query the current +/// time. The name "wall" makes an analogy to a "clock on the wall", which +/// is not necessarily monotonic as it may be reset. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +/// +/// A wall clock is a clock which measures the date and time according to +/// some external reference. +/// +/// External references may be reset, so this clock is not necessarily +/// monotonic, making it unsuitable for measuring elapsed time. +/// +/// It is intended for reporting the current date and time for humans. +@since(version = 0.2.0) +interface wall-clock { + /// A time and date in seconds plus nanoseconds. + @since(version = 0.2.0) + record datetime { + seconds: u64, + nanoseconds: u32, + } + + /// Read the current value of the clock. + /// + /// This clock is not monotonic, therefore calling this function repeatedly + /// will not necessarily produce a sequence of non-decreasing values. + /// + /// The returned timestamps represent the number of seconds since + /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], + /// also known as [Unix Time]. + /// + /// The nanoseconds field of the output is always less than 1000000000. + /// + /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 + /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time + @since(version = 0.2.0) + now: func() -> datetime; + + /// Query the resolution of the clock. + /// + /// The nanoseconds field of the output is always less than 1000000000. + @since(version = 0.2.0) + resolution: func() -> datetime; +} + +@unstable(feature = clocks-timezone) +interface timezone { + @unstable(feature = clocks-timezone) + use wall-clock.{datetime}; + + /// Information useful for displaying the timezone of a specific `datetime`. + /// + /// This information may vary within a single `timezone` to reflect daylight + /// saving time adjustments. + @unstable(feature = clocks-timezone) + record timezone-display { + /// The number of seconds difference between UTC time and the local + /// time of the timezone. + /// + /// The returned value will always be less than 86400 which is the + /// number of seconds in a day (24*60*60). + /// + /// In implementations that do not expose an actual time zone, this + /// should return 0. + utc-offset: s32, + /// The abbreviated name of the timezone to display to a user. The name + /// `UTC` indicates Coordinated Universal Time. Otherwise, this should + /// reference local standards for the name of the time zone. + /// + /// In implementations that do not expose an actual time zone, this + /// should be the string `UTC`. + /// + /// In time zones that do not have an applicable name, a formatted + /// representation of the UTC offset may be returned, such as `-04:00`. + name: string, + /// Whether daylight saving time is active. + /// + /// In implementations that do not expose an actual time zone, this + /// should return false. + in-daylight-saving-time: bool, + } + + /// Return information needed to display the given `datetime`. This includes + /// the UTC offset, the time zone name, and a flag indicating whether + /// daylight saving time is active. + /// + /// If the timezone cannot be determined for the given `datetime`, return a + /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight + /// saving time. + @unstable(feature = clocks-timezone) + display: func(when: datetime) -> timezone-display; + + /// The same as `display`, but only return the UTC offset. + @unstable(feature = clocks-timezone) + utc-offset: func(when: datetime) -> s32; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import wasi:io/poll@0.2.6; + @since(version = 0.2.0) + import monotonic-clock; + @since(version = 0.2.0) + import wall-clock; + @unstable(feature = clocks-timezone) + import timezone; +} diff --git a/examples/otel-service/wit/deps/wasi-io-0.2.6/package.wit b/examples/otel-service/wit/deps/wasi-io-0.2.6/package.wit new file mode 100644 index 0000000..99ec5b3 --- /dev/null +++ b/examples/otel-service/wit/deps/wasi-io-0.2.6/package.wit @@ -0,0 +1,11 @@ +package wasi:io@0.2.6; + +interface poll { + resource pollable { + ready: func() -> bool; + block: func(); + } + + poll: func(in: list>) -> list; +} + diff --git a/examples/otel-service/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit b/examples/otel-service/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit new file mode 100644 index 0000000..7230063 --- /dev/null +++ b/examples/otel-service/wit/deps/wasi-otel-0.2.0-rc.2+patch/package.wit @@ -0,0 +1,473 @@ +/// patched to use 0.2.6 instead of 0.2.0 for wasi:clocks and wasi:io +package wasi:otel@0.2.0-rc.2+patch; + +interface types { + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + /// + /// This corresponds with the `AnyValue` type defined in the [attribute spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue). + /// Because WIT doesn't support recursive types, the data needs to be serialized. JSON is used as the encoding format. + /// + /// Byte arrays require special encoding since JSON cannot distinguish them from number arrays. + /// They are base64-encoded with a prefix that follows the Data URI RFC 2397 convention: + /// `data:application/octet-stream;base64,` + type value = string; + + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// An immutable representation of the entity producing telemetry as attributes. + record %resource { + /// Attributes that identify the resource. + attributes: list, + /// The schema URL to be recorded in the emitted resource. + schema-url: option, + } + + /// Describes the instrumentation scope that produced telemetry. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + /// The library version. + version: option, + /// Schema URL used by this library. + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + schema-url: option, + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} + +interface tracing { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use types.{key-value, instrumentation-scope}; + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal, + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + /// Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; +} + +interface logs { + use types.{instrumentation-scope, %resource, value, key-value}; + use tracing.{span-id, trace-id, trace-flags}; + use wasi:clocks/wall-clock@0.2.6.{datetime}; + + /// Represents the recording of an event. + record log-record { + /// Time when the event occurred. + timestamp: option, + /// Time when the event was observed. + observed-timestamp: option, + /// The severity text(also known as log level). + severity-text: option, + /// The numerical value of the severity ranging from 1-24. + severity-number: option, + /// The body of the log record. + body: option, + /// Additional information about the specific event occurrence. + attributes: option>, + /// Name that identifies the class / type of event. + event-name: option, + /// Describes the source of the log. + %resource: option<%resource>, + /// Describes the scope that emitted the log. + instrumentation-scope: option, + /// Request trace id. + trace-id: option, + /// Request span id. + span-id: option, + /// W3C trace flag. + trace-flags: option, + } + + /// Called when a log is emitted. + on-emit: func(data: log-record); +} + +interface metrics { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use wasi:clocks/monotonic-clock@0.2.6.{duration}; + use types.{key-value, instrumentation-scope, %resource}; + use tracing.{span-id, trace-id}; + + /// An error resulting from `export` being called. + type error = string; + + /// A set of bucket counts, encoded in a contiguous array of counts. + record exponential-bucket { + /// The bucket index of the first entry in the `counts` list. + offset: s32, + /// A list where `counts[i]` carries the count of the bucket at index `offset + i`. + /// + /// `counts[i]` is the count of values greater than base^(offset+i) and less than + /// or equal to base^(offset+i+1). + counts: list, + } + + /// Defines the window that an aggregation was calculated over. + enum temporality { + /// A measurement interval that continues to expand forward in time from a + /// starting point. + /// + /// New measurements are added to all previous measurements since a start time. + /// + /// This is the default temporality. + cumulative, + /// A measurement interval that resets each cycle. + /// + /// Measurements from one cycle are recorded independently, measurements from + /// other cycles do not affect them. + delta, + /// Configures Synchronous Counter and Histogram instruments to use + /// Delta aggregation temporality, which allows them to shed memory + /// following a cardinality explosion, thus use less memory. + low-memory, + } + + /// The number types available for any given instrument. + variant metric-number { + %f64(f64), + %s64(s64), + %u64(u64), + } + + /// A measurement sampled from a time series providing a typical example. + record exemplar { + /// The attributes recorded with the measurement but filtered out of the + /// time series' aggregated data. + filtered-attributes: list, + /// The time when the measurement was recorded. + time: datetime, + /// The measured value. + value: metric-number, + /// The ID of the span that was active during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + span-id: span-id, + /// The ID of the trace the active span belonged to during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + trace-id: trace-id, + } + + /// A single data point in a time series to be associated with a `gauge`. + record gauge-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// A measurement of the current value of an instrument. + record gauge { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: option, + /// The time when the time series was recorded. + time: datetime, + } + + /// A single data point in a time series to be associated with a `sum`. + record sum-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the sum of all measurements of values from an instrument. + record sum { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + /// Whether this aggregation only increases or decreases. + is-monotonic: bool, + } + + /// A single data point in a time series to be associated with a `histogram`. + record histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The upper bounds of the buckets of the histogram. + bounds: list, + /// The count of each of the buckets. + bucket-counts: list, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The sum of the values recorded + sum: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the histogram of all measurements of values from an instrument. + record histogram { + /// Individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with an `exponential-histogram `. + record exponential-histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The maximum value recorded. + sum: metric-number, + /// Describes the resolution of the histogram. + /// + /// Boundaries are located at powers of the base, where: + /// + /// base = 2 ^ (2 ^ -scale) + scale: s8, + /// The number of values whose absolute value is less than or equal to + /// `zero_threshold`. + /// + /// When `zero_threshold` is `0`, this is the number of values that cannot be + /// expressed using the standard exponential formula as well as values that have + /// been rounded to zero. + zero-count: u64, + /// The range of positive value bucket counts. + positive-bucket: exponential-bucket, + /// The range of negative value bucket counts. + negative-bucket: exponential-bucket, + /// The width of the zero region. + /// + /// Where the zero region is defined as the closed interval + /// [-zero_threshold, zero_threshold]. + zero-threshold: f64, + /// The sampled exemplars collected during the time series. + exemplars: list, + } + + /// The histogram of all measurements of values from an instrument. + record exponential-histogram { + /// The individual aggregated measurements with unique attributes. + data-points: list, + /// When the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// Metric data for all types. + variant metric-data { + /// Metric data for an f64 gauge. + f64-gauge(gauge), + /// Metric data for an f64 sum. + f64-sum(sum), + /// Metric data for an f64 histogram. + f64-histogram(histogram), + /// Metric data for an f64 exponential-histogram. + f64-exponential-histogram(exponential-histogram), + /// Metric data for an u64 gauge. + u64-gauge(gauge), + /// Metric data for an u64 sum. + u64-sum(sum), + /// Metric data for an u64 histogram. + u64-histogram(histogram), + /// Metric data for an u64 exponential-histogram. + u64-exponential-histogram(exponential-histogram), + /// Metric data for an s64 gauge. + s64-gauge(gauge), + /// Metric data for an s64 sum. + s64-sum(sum), + /// Metric data for an s64 histogram. + s64-histogram(histogram), + /// Metric data for an s64 exponential-histogram. + s64-exponential-histogram(exponential-histogram), + } + + /// A collection of one or more aggregated time series from a metric. + record metric { + /// The name of the metric that created this data. + name: string, + /// The description of the metric, which can be used in documentation. + description: string, + /// The unit in which the metric reports. + unit: string, + /// The aggregated data from a metric. + data: metric-data, + } + + /// A collection of `metric`s produced by a meter. + record scope-metrics { + /// The instrumentation scope that the meter was created with. + scope: instrumentation-scope, + /// The list of aggregations created by the meter. + metrics: list, + } + + /// A collection of `scope-metrics` and the associated `resource` that created them. + record resource-metrics { + /// The entity that collected the metrics. + %resource: %resource, + /// The collection of metrics with unique `instrumentation-scope`s. + scope-metrics: list, + } + + /// Exports a resource's metric data. + %export: func(metrics: resource-metrics) -> result<_, error>; +} + +world imports { + import types; + import wasi:clocks/wall-clock@0.2.6; + import tracing; + import wasi:io/poll@0.2.6; + import wasi:clocks/monotonic-clock@0.2.6; + import metrics; + import logs; +} diff --git a/examples/otel-service/wit/deps/wasi-random-0.2.6/package.wit b/examples/otel-service/wit/deps/wasi-random-0.2.6/package.wit new file mode 100644 index 0000000..73edf5b --- /dev/null +++ b/examples/otel-service/wit/deps/wasi-random-0.2.6/package.wit @@ -0,0 +1,92 @@ +package wasi:random@0.2.6; + +/// The insecure-seed interface for seeding hash-map DoS resistance. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure-seed { + /// Return a 128-bit value that may contain a pseudo-random value. + /// + /// The returned value is not required to be computed from a CSPRNG, and may + /// even be entirely deterministic. Host implementations are encouraged to + /// provide pseudo-random values to any program exposed to + /// attacker-controlled content, to enable DoS protection built into many + /// languages' hash-map implementations. + /// + /// This function is intended to only be called once, by a source language + /// to initialize Denial Of Service (DoS) protection in its hash-map + /// implementation. + /// + /// # Expected future evolution + /// + /// This will likely be changed to a value import, to prevent it from being + /// called multiple times and potentially used for purposes other than DoS + /// protection. + @since(version = 0.2.0) + insecure-seed: func() -> tuple; +} + +/// The insecure interface for insecure pseudo-random numbers. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface insecure { + /// Return `len` insecure pseudo-random bytes. + /// + /// This function is not cryptographically secure. Do not use it for + /// anything related to security. + /// + /// There are no requirements on the values of the returned bytes, however + /// implementations are encouraged to return evenly distributed values with + /// a long period. + @since(version = 0.2.0) + get-insecure-random-bytes: func(len: u64) -> list; + + /// Return an insecure pseudo-random `u64` value. + /// + /// This function returns the same type of pseudo-random data as + /// `get-insecure-random-bytes`, represented as a `u64`. + @since(version = 0.2.0) + get-insecure-random-u64: func() -> u64; +} + +/// WASI Random is a random data API. +/// +/// It is intended to be portable at least between Unix-family platforms and +/// Windows. +@since(version = 0.2.0) +interface random { + /// Return `len` cryptographically-secure random or pseudo-random bytes. + /// + /// This function must produce data at least as cryptographically secure and + /// fast as an adequately seeded cryptographically-secure pseudo-random + /// number generator (CSPRNG). It must not block, from the perspective of + /// the calling program, under any circumstances, including on the first + /// request and on requests for numbers of bytes. The returned data must + /// always be unpredictable. + /// + /// This function must always return fresh data. Deterministic environments + /// must omit this function, rather than implementing it with deterministic + /// data. + @since(version = 0.2.0) + get-random-bytes: func(len: u64) -> list; + + /// Return a cryptographically-secure random or pseudo-random `u64` value. + /// + /// This function returns the same type of data as `get-random-bytes`, + /// represented as a `u64`. + @since(version = 0.2.0) + get-random-u64: func() -> u64; +} + +@since(version = 0.2.0) +world imports { + @since(version = 0.2.0) + import random; + @since(version = 0.2.0) + import insecure; + @since(version = 0.2.0) + import insecure-seed; +} diff --git a/examples/otel-service/wit/guest.wit b/examples/otel-service/wit/guest.wit new file mode 100644 index 0000000..1ff06c5 --- /dev/null +++ b/examples/otel-service/wit/guest.wit @@ -0,0 +1,10 @@ +package example:otel-capability; + +world guest { + import wasi:otel/logs@0.2.0-rc.2+patch; + import wasi:otel/tracing@0.2.0-rc.2+patch; + import wasi:otel/types@0.2.0-rc.2+patch; + import wasi:random/random@0.2.6; + + export run: func() -> result<_, string>; +} diff --git a/examples/otel-service/wit/overrides/wasi-otel/logs.wit b/examples/otel-service/wit/overrides/wasi-otel/logs.wit new file mode 100644 index 0000000..69f133c --- /dev/null +++ b/examples/otel-service/wit/overrides/wasi-otel/logs.wit @@ -0,0 +1,36 @@ +interface logs { + use types.{instrumentation-scope, %resource, value, key-value}; + use tracing.{span-id, trace-id, trace-flags}; + use wasi:clocks/wall-clock@0.2.6.{datetime}; + + /// Called when a log is emitted. + on-emit: func(data: log-record); + + /// Represents the recording of an event. + record log-record { + /// Time when the event occurred. + timestamp: option, + /// Time when the event was observed. + observed-timestamp: option, + /// The severity text(also known as log level). + severity-text: option, + /// The numerical value of the severity ranging from 1-24. + severity-number: option, + /// The body of the log record. + body: option, + /// Additional information about the specific event occurrence. + attributes: option>, + /// Name that identifies the class / type of event. + event-name: option, + /// Describes the source of the log. + %resource: option<%resource>, + /// Describes the scope that emitted the log. + instrumentation-scope: option, + /// Request trace id. + trace-id: option, + /// Request span id. + span-id: option, + /// W3C trace flag. + trace-flags: option, + } +} diff --git a/examples/otel-service/wit/overrides/wasi-otel/metrics.wit b/examples/otel-service/wit/overrides/wasi-otel/metrics.wit new file mode 100644 index 0000000..8ba58c7 --- /dev/null +++ b/examples/otel-service/wit/overrides/wasi-otel/metrics.wit @@ -0,0 +1,256 @@ +interface metrics { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use wasi:clocks/monotonic-clock@0.2.6.{duration}; + use types.{key-value, instrumentation-scope, %resource}; + use tracing.{span-id, trace-id}; + + /// Exports a resource's metric data. + %export: func(metrics: resource-metrics) -> result<_, error>; + + /// An error resulting from `export` being called. + type error = string; + + /// A collection of `scope-metrics` and the associated `resource` that created them. + record resource-metrics { + /// The entity that collected the metrics. + %resource: %resource, + /// The collection of metrics with unique `instrumentation-scope`s. + scope-metrics: list, + } + + /// A collection of `metric`s produced by a meter. + record scope-metrics { + /// The instrumentation scope that the meter was created with. + scope: instrumentation-scope, + /// The list of aggregations created by the meter. + metrics: list, + } + + /// A collection of one or more aggregated time series from a metric. + record metric { + /// The name of the metric that created this data. + name: string, + /// The description of the metric, which can be used in documentation. + description: string, + /// The unit in which the metric reports. + unit: string, + /// The aggregated data from a metric. + data: metric-data + } + + /// Metric data for all types. + variant metric-data { + /// Metric data for an f64 gauge. + f64-gauge(gauge), + /// Metric data for an f64 sum. + f64-sum(sum), + /// Metric data for an f64 histogram. + f64-histogram(histogram), + /// Metric data for an f64 exponential-histogram. + f64-exponential-histogram(exponential-histogram), + /// Metric data for an u64 gauge. + u64-gauge(gauge), + /// Metric data for an u64 sum. + u64-sum(sum), + /// Metric data for an u64 histogram. + u64-histogram(histogram), + /// Metric data for an u64 exponential-histogram. + u64-exponential-histogram(exponential-histogram), + /// Metric data for an s64 gauge. + s64-gauge(gauge), + /// Metric data for an s64 sum. + s64-sum(sum), + /// Metric data for an s64 histogram. + s64-histogram(histogram), + /// Metric data for an s64 exponential-histogram. + s64-exponential-histogram(exponential-histogram), + } + + /// A measurement of the current value of an instrument. + record gauge { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: option, + /// The time when the time series was recorded. + time: datetime, + } + + /// A single data point in a time series to be associated with a `gauge`. + record gauge-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the sum of all measurements of values from an instrument. + record sum { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + /// Whether this aggregation only increases or decreases. + is-monotonic: bool, + } + + /// A single data point in a time series to be associated with a `sum`. + record sum-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the histogram of all measurements of values from an instrument. + record histogram { + /// Individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with a `histogram`. + record histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The upper bounds of the buckets of the histogram. + bounds: list, + /// The count of each of the buckets. + bucket-counts: list, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The sum of the values recorded + sum: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// The histogram of all measurements of values from an instrument. + record exponential-histogram { + /// The individual aggregated measurements with unique attributes. + data-points: list, + /// When the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with an `exponential-histogram `. + record exponential-histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The maximum value recorded. + sum: metric-number, + /// Describes the resolution of the histogram. + /// + /// Boundaries are located at powers of the base, where: + /// + /// base = 2 ^ (2 ^ -scale) + scale: s8, + /// The number of values whose absolute value is less than or equal to + /// `zero_threshold`. + /// + /// When `zero_threshold` is `0`, this is the number of values that cannot be + /// expressed using the standard exponential formula as well as values that have + /// been rounded to zero. + zero-count: u64, + /// The range of positive value bucket counts. + positive-bucket: exponential-bucket, + /// The range of negative value bucket counts. + negative-bucket: exponential-bucket, + /// The width of the zero region. + /// + /// Where the zero region is defined as the closed interval + /// [-zero_threshold, zero_threshold]. + zero-threshold: f64, + /// The sampled exemplars collected during the time series. + exemplars: list, + } + + /// A set of bucket counts, encoded in a contiguous array of counts. + record exponential-bucket { + /// The bucket index of the first entry in the `counts` list. + offset: s32, + /// A list where `counts[i]` carries the count of the bucket at index `offset + i`. + /// + /// `counts[i]` is the count of values greater than base^(offset+i) and less than + /// or equal to base^(offset+i+1). + counts: list, + } + + /// A measurement sampled from a time series providing a typical example. + record exemplar { + /// The attributes recorded with the measurement but filtered out of the + /// time series' aggregated data. + filtered-attributes: list, + /// The time when the measurement was recorded. + time: datetime, + /// The measured value. + value: metric-number, + /// The ID of the span that was active during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + span-id: span-id, + /// The ID of the trace the active span belonged to during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + trace-id: trace-id, + } + + /// Defines the window that an aggregation was calculated over. + enum temporality { + /// A measurement interval that continues to expand forward in time from a + /// starting point. + /// + /// New measurements are added to all previous measurements since a start time. + /// + /// This is the default temporality. + cumulative, + /// A measurement interval that resets each cycle. + /// + /// Measurements from one cycle are recorded independently, measurements from + /// other cycles do not affect them. + delta, + /// Configures Synchronous Counter and Histogram instruments to use + /// Delta aggregation temporality, which allows them to shed memory + /// following a cardinality explosion, thus use less memory. + low-memory, + } + + /// The number types available for any given instrument. + variant metric-number { + %f64(f64), + %s64(s64), + %u64(u64), + } +} diff --git a/examples/otel-service/wit/overrides/wasi-otel/tracing.wit b/examples/otel-service/wit/overrides/wasi-otel/tracing.wit new file mode 100644 index 0000000..9d0f7ff --- /dev/null +++ b/examples/otel-service/wit/overrides/wasi-otel/tracing.wit @@ -0,0 +1,122 @@ +interface tracing { + use wasi:clocks/wall-clock@0.2.6.{datetime}; + use types.{key-value, instrumentation-scope}; + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + // Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } +} diff --git a/examples/otel-service/wit/overrides/wasi-otel/types.wit b/examples/otel-service/wit/overrides/wasi-otel/types.wit new file mode 100644 index 0000000..6fa87b5 --- /dev/null +++ b/examples/otel-service/wit/overrides/wasi-otel/types.wit @@ -0,0 +1,46 @@ +interface types { + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + /// + /// This corresponds with the `AnyValue` type defined in the [attribute spec](https://opentelemetry.io/docs/specs/otel/common/#anyvalue). + /// Because WIT doesn't support recursive types, the data needs to be serialized. JSON is used as the encoding format. + /// + /// Byte arrays require special encoding since JSON cannot distinguish them from number arrays. + /// They are base64-encoded with a prefix that follows the Data URI RFC 2397 convention: + /// `data:application/octet-stream;base64,` + type value = string; + + /// An immutable representation of the entity producing telemetry as attributes. + record %resource { + /// Attributes that identify the resource. + attributes: list, + /// The schema URL to be recorded in the emitted resource. + schema-url: option, + } + + /// Describes the instrumentation scope that produced telemetry. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + + /// The library version. + version: option, + + /// Schema URL used by this library. + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + schema-url: option, + + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} diff --git a/examples/otel-service/wit/overrides/wasi-otel/world.wit b/examples/otel-service/wit/overrides/wasi-otel/world.wit new file mode 100644 index 0000000..ec32b34 --- /dev/null +++ b/examples/otel-service/wit/overrides/wasi-otel/world.wit @@ -0,0 +1,9 @@ +/// patched to use 0.2.6 instead of 0.2.0 for wasi:clocks and wasi:io +package wasi:otel@0.2.0-rc.2+patch; + +world imports { + import types; + import tracing; + import metrics; + import logs; +} diff --git a/examples/otel-service/wkg.lock b/examples/otel-service/wkg.lock new file mode 100644 index 0000000..d093fe5 --- /dev/null +++ b/examples/otel-service/wkg.lock @@ -0,0 +1,21 @@ +# This file is automatically generated. +# It is not intended for manual editing. +version = 1 + +[[packages]] +name = "wasi:clocks" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.6" +version = "0.2.6" +digest = "sha256:569984cc45d3f5a362a3b2897aabbaa3cc4184a6113bfcbbf03c1bd7fc20338c" + +[[packages]] +name = "wasi:random" +registry = "wasi.dev" + +[[packages.versions]] +requirement = "=0.2.6" +version = "0.2.6" +digest = "sha256:14ea24097cbe19ae2c79c6ffead72f70c4aed65bb68ef40ed8eca6e08383dc1b" diff --git a/examples/otel-service/wkg.toml b/examples/otel-service/wkg.toml new file mode 100644 index 0000000..aa772d3 --- /dev/null +++ b/examples/otel-service/wkg.toml @@ -0,0 +1,2 @@ +[overrides] +"wasi:otel" = { path = "./wit/overrides/wasi-otel" } diff --git a/examples/service/Cargo.lock b/examples/service/Cargo.lock index 5b9ac55..b02ebf9 100644 --- a/examples/service/Cargo.lock +++ b/examples/service/Cargo.lock @@ -652,7 +652,7 @@ dependencies = [ [[package]] name = "composable-interceptor" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -666,7 +666,7 @@ dependencies = [ [[package]] name = "composable-runtime" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "anyhow", "clap", diff --git a/examples/service/host/src/main.rs b/examples/service/host/src/main.rs index 7c280d0..9e44f73 100644 --- a/examples/service/host/src/main.rs +++ b/examples/service/host/src/main.rs @@ -150,7 +150,14 @@ async fn main() -> Result<()> { runtime.start()?; let result = runtime - .invoke("greeter", "greet", vec![serde_json::json!("World")]) + .invoker() + .invoke( + "greeter", + "greet", + vec![serde_json::json!("World")], + None, + None, + ) .await?; println!("Result: {result}"); diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 0000000..04d37a3 --- /dev/null +++ b/src/context.rs @@ -0,0 +1,17 @@ +//! Context propagated across service boundaries. +//! +//! `PROPAGATION_CONTEXT` is a tokio task-local that carries key/value entries +//! (e.g. W3C traceparent, tracestate, baggage) across invocation and messaging +//! boundaries. Scoped by `ComponentInvoker` and transport entry points. +//! Readers should use `try_with` to handle the case where no scope is active. + +use std::collections::HashMap; + +/// Per-invocation context carrying propagated key/value entries. +pub struct PropagationContext { + pub entries: HashMap, +} + +tokio::task_local! { + pub static PROPAGATION_CONTEXT: Option; +} diff --git a/src/lib.rs b/src/lib.rs index 0b50ecc..32e80dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,11 +8,12 @@ pub use composition::registry::{CapabilityStateHasData, HostCapability, HostCapa pub use config::types::{ CategoryClaim, Condition, ConfigHandler, DefinitionLoader, Operator, PropertyMap, Selector, }; +pub use context::{PROPAGATION_CONTEXT, PropagationContext}; pub use runtime::{Runtime, RuntimeBuilder}; pub use service::Service; pub use types::{ CapabilityDefinition, Component, ComponentDefinition, ComponentInvoker, ComponentMetadata, - ComponentState, Function, FunctionParam, MessagePublisher, + ComponentState, Function, FunctionParam, MessagePublisher, PROPAGATED_HEADERS, }; // exposed for testing, hidden from docs @@ -22,6 +23,7 @@ pub mod composition; pub mod types; pub(crate) mod config; +pub(crate) mod context; #[cfg(feature = "messaging")] mod messaging; mod runtime; diff --git a/src/main.rs b/src/main.rs index adeae14..97a7d38 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use composable_runtime::{Component, ComponentGraph, FunctionParam, Runtime, Sele use rustyline::Editor; use rustyline::error::ReadlineError; use rustyline::history::DefaultHistory; +use std::collections::HashMap; use std::path::PathBuf; use tracing_subscriber::EnvFilter; @@ -23,6 +24,14 @@ enum Command { #[arg(required = true)] definitions: Vec, + /// Propagation context entries (KEY=VALUE) + #[arg(long = "ctx", value_parser = parse_key_value)] + ctx: Vec<(String, String)>, + + /// Environment variables (KEY=VALUE) + #[arg(long = "env", value_parser = parse_key_value)] + env: Vec<(String, String)>, + /// Target and arguments, passed after -- #[arg(last = true)] target_args: Vec, @@ -42,6 +51,10 @@ enum Command { /// Filter components by selector (e.g. labels.domain=payments, !dependents, name in (foo, bar)) #[arg(long)] selector: Option, + + /// Environment variables (KEY=VALUE) + #[arg(long = "env", value_parser = parse_key_value)] + env: Vec<(String, String)>, }, /// Publish a message to a channel Publish { @@ -96,20 +109,26 @@ async fn main() -> Result<()> { Command::Shell { definitions, selector, + env, } => { let selector = selector.map(|s| Selector::parse(&s)).transpose()?; + let env = vec_to_option_map(env); let runtime = Runtime::builder().from_paths(&definitions).build().await?; runtime.start()?; - run_shell(&runtime, selector.as_ref()).await?; + run_shell(&runtime, selector.as_ref(), env.as_ref()).await?; runtime.shutdown().await; } Command::Invoke { definitions, + ctx, + env, target_args, } => { + let context = vec_to_option_map(ctx); + let env = vec_to_option_map(env); let runtime = Runtime::builder().from_paths(&definitions).build().await?; runtime.start()?; - run_invoke(&runtime, target_args).await?; + run_invoke(&runtime, target_args, context, env).await?; runtime.shutdown().await; } Command::Publish { @@ -154,7 +173,12 @@ fn build_graph(definitions: &[PathBuf]) -> Result { ComponentGraph::builder().from_paths(definitions).build() } -async fn run_invoke(runtime: &Runtime, target_args: Vec) -> Result<()> { +async fn run_invoke( + runtime: &Runtime, + target_args: Vec, + context: Option>, + env: Option>, +) -> Result<()> { let (target, args) = target_args .split_first() .ok_or_else(|| anyhow::anyhow!("missing target after --"))?; @@ -176,13 +200,18 @@ async fn run_invoke(runtime: &Runtime, target_args: Vec) -> Result<()> { parse_invoke_args(args, function.params()).map_err(|e| anyhow::anyhow!("{e}"))?; let result = runtime - .invoke(component_name, func_name, final_args) + .invoker() + .invoke(component_name, func_name, final_args, context, env) .await?; println!("{}", serde_json::to_string_pretty(&result)?); Ok(()) } -async fn run_shell(runtime: &Runtime, selector: Option<&Selector>) -> Result<()> { +async fn run_shell( + runtime: &Runtime, + selector: Option<&Selector>, + env: Option<&HashMap>, +) -> Result<()> { let components = runtime.list_components(selector); if selector.is_some() { @@ -203,7 +232,10 @@ async fn run_shell(runtime: &Runtime, selector: Option<&Selector>) -> Result<()> match readline { Ok(line) => { let _ = rl.add_history_entry(line.as_str()); - if handle_command(line, runtime, &components).await.is_err() { + if handle_command(line, runtime, &components, env) + .await + .is_err() + { break; } } @@ -229,6 +261,7 @@ async fn handle_command( line: String, runtime: &Runtime, components: &[&Component], + env: Option<&HashMap>, ) -> Result<(), ()> { let parts = parse_quoted_args(&line); @@ -341,7 +374,14 @@ async fn handle_command( Ok(final_args) => { println!("Invoking {target}..."); match runtime - .invoke(component_name, func_name, final_args) + .invoker() + .invoke( + component_name, + func_name, + final_args, + None, + env.cloned(), + ) .await { Ok(result) => { @@ -460,3 +500,14 @@ fn parse_quoted_args(line: &str) -> Vec { } parts } + +fn parse_key_value(s: &str) -> Result<(String, String), String> { + let (key, value) = s + .split_once('=') + .ok_or_else(|| format!("expected KEY=VALUE, got '{s}'"))?; + Ok((key.to_string(), value.to_string())) +} + +fn vec_to_option_map(pairs: Vec<(String, String)>) -> Option> { + (!pairs.is_empty()).then(|| pairs.into_iter().collect()) +} diff --git a/src/messaging/activator.rs b/src/messaging/activator.rs index d356c9c..9fdca72 100644 --- a/src/messaging/activator.rs +++ b/src/messaging/activator.rs @@ -1,7 +1,7 @@ use std::future::Future; use std::sync::Arc; -use crate::types::{Component, ComponentInvoker}; +use crate::types::{Component, ComponentInvoker, PROPAGATED_HEADERS}; use super::channel::ReplyPublisher; use super::message::{Message, MessageBuilder, header}; @@ -169,12 +169,21 @@ impl Handler for Activator { InvocationMode::Direct => Err("direct handler mode not yet implemented".to_string()), InvocationMode::Mapped { mapper } => { let invocation = mapper.map(&msg)?; + let mut context = std::collections::HashMap::new(); + for key in PROPAGATED_HEADERS { + if let Some(val) = msg.headers().get::<&str>(key) { + context.insert((*key).to_string(), val.to_string()); + } + } + let context = (!context.is_empty()).then_some(context); let result = self .invoker .invoke( &self.component_name, &invocation.function_key, invocation.args, + context, + None, ) .await .map_err(|e| e.to_string())?; diff --git a/src/messaging/service.rs b/src/messaging/service.rs index bd2c44b..a413033 100644 --- a/src/messaging/service.rs +++ b/src/messaging/service.rs @@ -6,8 +6,9 @@ use std::sync::{Arc, Mutex}; use anyhow::Result; use crate::config::types::{CategoryClaim, ConfigHandler, PropertyMap}; +use crate::context::PROPAGATION_CONTEXT; use crate::service::Service; -use crate::types::{ComponentInvoker, MessagePublisher}; +use crate::types::{ComponentInvoker, MessagePublisher, PROPAGATED_HEADERS}; use super::bus::{Bus, LocalBus, LocalChannelFactory, SubscriptionConfig}; use super::message::MessageBuilder; @@ -115,6 +116,19 @@ impl MessagePublisher for BusPublisher { ) -> Pin> + Send + 'a>> { Box::pin(async move { let mut builder = MessageBuilder::new(body); + // Merge propagated context entries into outgoing message headers. + if let Some(entries) = PROPAGATION_CONTEXT + .try_with(|ctx| ctx.as_ref().map(|c| c.entries.clone())) + .ok() + .flatten() + { + for key in PROPAGATED_HEADERS { + if let Some(val) = entries.get(*key) { + builder = builder.header(*key, val.as_str()); + } + } + } + // Caller-supplied headers may override propagated entries. for (key, value) in headers { builder = builder.header(key, value); } diff --git a/src/runtime/host.rs b/src/runtime/host.rs index 1202ad1..405dad2 100644 --- a/src/runtime/host.rs +++ b/src/runtime/host.rs @@ -19,7 +19,10 @@ use wasmtime_wasi_http::{HttpResult, WasiHttpCtx, WasiHttpView}; use wasmtime_wasi_io::IoView; use crate::composition::registry::{CapabilityRegistry, ComponentRegistry}; -use crate::types::{Component, ComponentInvoker, ComponentMetadata, ComponentState, Function}; +use crate::context::{PROPAGATION_CONTEXT, PropagationContext}; +use crate::types::{ + Component, ComponentInvoker, ComponentMetadata, ComponentState, Function, PROPAGATED_HEADERS, +}; // Component host: wasmtime engine + registries, provides instantiation + invocation. #[derive(Clone)] @@ -66,7 +69,7 @@ impl ComponentHost { component_name: &str, function_name: &str, args: Vec, - env_vars: &[(&str, &str)], + env_vars: &[(String, String)], ) -> Result { let spec = self .component_registry @@ -92,7 +95,7 @@ impl ComponentHost { pub(crate) async fn instantiate( &self, component_name: &str, - env_vars: &[(&str, &str)], + env_vars: &[(String, String)], ) -> Result<(Store, wasmtime::component::Instance)> { let spec = self .component_registry @@ -134,10 +137,24 @@ impl ComponentInvoker for ComponentHost { component_name: &'a str, function_name: &'a str, args: Vec, + context: Option>, + env: Option>, ) -> std::pin::Pin< Box> + Send + 'a>, > { - Box::pin(self.invoke(component_name, function_name, args, &[])) + Box::pin(async move { + let env_pairs: Vec<(String, String)> = + env.map(|m| m.into_iter().collect()).unwrap_or_default(); + let fut = self.invoke(component_name, function_name, args, &env_pairs); + match context { + Some(entries) => { + let ctx = PropagationContext { entries }; + PROPAGATION_CONTEXT.scope(Some(ctx), fut).await + } + // None: inherit upstream propagation context if present. + None => fut.await, + } + }) } } @@ -169,9 +186,24 @@ impl WasiHttpView for ComponentState { fn send_request( &mut self, - request: hyper::Request, + mut request: hyper::Request, config: OutgoingRequestConfig, ) -> HttpResult { + // Propagate context entries to outgoing HTTP requests if present. + let ctx_entries: Option> = PROPAGATION_CONTEXT + .try_with(|ctx| ctx.as_ref().map(|c| c.entries.clone())) + .ok() + .flatten(); + if let Some(entries) = ctx_entries { + for key in PROPAGATED_HEADERS { + if let Some(val) = entries.get(*key) + && let Ok(hv) = val.parse() + { + request.headers_mut().insert(*key, hv); + } + } + } + let is_grpc = request .headers() .get("content-type") @@ -335,7 +367,7 @@ impl Invoker { bytes: &[u8], capabilities: &[String], capability_registry: &CapabilityRegistry, - env_vars: &[(&str, &str)], + env_vars: &[(String, String)], ) -> Result<(Store, wasmtime::component::Instance)> { let component_bytes = bytes.to_vec(); let linker = self.create_linker(capabilities, capability_registry)?; @@ -437,7 +469,7 @@ impl Invoker { capability_registry: &CapabilityRegistry, function: Function, args: Vec, - env_vars: &[(&str, &str)], + env_vars: &[(String, String)], ) -> Result { let function_name = function.function_name(); diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index a3c8720..866f480 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -44,50 +44,18 @@ impl Runtime { self.host.get_component(name) } - /// Invoke a component function - pub async fn invoke( - &self, - component_name: &str, - function_name: &str, - args: Vec, - ) -> Result { - ComponentInvoker::invoke(&self.host, component_name, function_name, args).await - } - - /// Invoke a component function with environment variables - pub async fn invoke_with_env( - &self, - component_name: &str, - function_name: &str, - args: Vec, - env_vars: &[(&str, &str)], - ) -> Result { - self.host - .invoke(component_name, function_name, args, env_vars) - .await - } - /// Instantiate a component pub async fn instantiate( &self, component_name: &str, + env: Option>, ) -> Result<( wasmtime::Store, wasmtime::component::Instance, )> { - self.instantiate_with_env(component_name, &[]).await - } - - /// Instantiate a component with environment variables - pub async fn instantiate_with_env( - &self, - component_name: &str, - env_vars: &[(&str, &str)], - ) -> Result<( - wasmtime::Store, - wasmtime::component::Instance, - )> { - self.host.instantiate(component_name, env_vars).await + let env_pairs: Vec<(String, String)> = + env.map(|m| m.into_iter().collect()).unwrap_or_default(); + self.host.instantiate(component_name, &env_pairs).await } /// Get a component invoker for this runtime. diff --git a/src/types.rs b/src/types.rs index 82606c3..2bc2c03 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,6 +7,9 @@ use std::fmt; use std::future::Future; use std::pin::Pin; +/// Base set of header keys that should be propagated across service boundaries. +pub const PROPAGATED_HEADERS: &[&str] = &["traceparent", "tracestate", "baggage"]; + pub fn default_scope() -> String { "any".to_string() } @@ -276,6 +279,8 @@ pub trait ComponentInvoker: Send + Sync { component_name: &'a str, function_name: &'a str, args: Vec, + context: Option>, + env: Option>, ) -> Pin> + Send + 'a>>; } diff --git a/tests/host_capabilities.rs b/tests/host_capabilities.rs index 2b712ff..f3b8f75 100644 --- a/tests/host_capabilities.rs +++ b/tests/host_capabilities.rs @@ -170,7 +170,8 @@ async fn test_host_capability_invoked() { .expect("Failed to create runtime"); let result = runtime - .invoke("guest", "get-value", vec![]) + .invoker() + .invoke("guest", "get-value", vec![], None, None) .await .expect("Failed to invoke"); @@ -264,7 +265,8 @@ async fn test_host_capability_with_config() { .expect("Failed to create runtime"); let result = runtime - .invoke("guest", "calc", vec![]) + .invoker() + .invoke("guest", "calc", vec![], None, None) .await .expect("Failed to invoke"); @@ -299,7 +301,8 @@ async fn test_host_capability_with_default_config() { .expect("Failed to create runtime"); let result = runtime - .invoke("guest", "calc", vec![]) + .invoker() + .invoke("guest", "calc", vec![], None, None) .await .expect("Failed to invoke"); @@ -397,7 +400,8 @@ async fn test_host_capability_with_state() { .expect("Failed to create runtime"); let result = runtime - .invoke("guest", "count-twice", vec![]) + .invoker() + .invoke("guest", "count-twice", vec![], None, None) .await .expect("Failed to invoke"); @@ -432,14 +436,16 @@ async fn test_host_capability_state_isolated_per_instance() { // First invocation let result1 = runtime - .invoke("guest", "count-twice", vec![]) + .invoker() + .invoke("guest", "count-twice", vec![], None, None) .await .expect("Failed to invoke"); assert_eq!(result1, serde_json::json!(2)); // Second invocation - should start fresh (new instance, new state) let result2 = runtime - .invoke("guest", "count-twice", vec![]) + .invoker() + .invoke("guest", "count-twice", vec![], None, None) .await .expect("Failed to invoke"); assert_eq!(result2, serde_json::json!(2)); @@ -540,7 +546,7 @@ async fn test_duplicate_capability_state_type_fails() { .expect("Failed to create runtime"); // State is created during instantiation, not during build - let result = runtime.instantiate("guest").await; + let result = runtime.instantiate("guest", None).await; // Should fail because both capabilities try to register SharedState match result {