feat(http): initialize alknet-http crate with module skeleton

Add crates/alknet-http with Cargo.toml, src/lib.rs, and the five
subsystem modules (server, gateway, client, adapters, websocket) per
ADR-039 (server + client host colocated). The mcp feature gate pulls in
rmcp with streamable HTTP transport features only (ADR-037 — no stdio);
h3/WebTransport is absent (deferred per ADR-044). alknet-core and
alknet-call use workspace path deps. The crate is added to the workspace
members list.
This commit is contained in:
2026-07-01 16:41:14 +00:00
parent e855c8c7eb
commit c2e6ba5b96
9 changed files with 458 additions and 4 deletions

368
Cargo.lock generated
View File

@@ -99,6 +99,29 @@ dependencies = [
"zeroize",
]
[[package]]
name = "alknet-http"
version = "0.1.0"
dependencies = [
"alknet-call",
"alknet-core",
"async-trait",
"axum",
"futures",
"hyper",
"openapiv3",
"reqwest 0.13.4",
"reqwest-middleware",
"reqwest-retry",
"rmcp",
"serde",
"serde_json",
"thiserror 2.0.18",
"tokio",
"tracing",
"uuid",
]
[[package]]
name = "alknet-vault"
version = "0.1.0"
@@ -381,6 +404,61 @@ dependencies = [
"fs_extra",
]
[[package]]
name = "axum"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
dependencies = [
"axum-core",
"base64",
"bytes",
"form_urlencoded",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"serde_core",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sha1",
"sync_wrapper",
"tokio",
"tokio-tungstenite",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"sync_wrapper",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "backon"
version = "1.6.0"
@@ -1804,6 +1882,8 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
@@ -1885,7 +1965,7 @@ dependencies = [
"portmapper",
"rand 0.8.6",
"rcgen 0.13.2",
"reqwest",
"reqwest 0.12.28",
"ring",
"rustls",
"rustls-webpki 0.102.8",
@@ -2031,7 +2111,7 @@ dependencies = [
"pkarr",
"postcard",
"rand 0.8.6",
"reqwest",
"reqwest 0.12.28",
"rustls",
"rustls-webpki 0.102.8",
"serde",
@@ -2248,6 +2328,12 @@ dependencies = [
"regex-automata",
]
[[package]]
name = "matchit"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "md5"
version = "0.7.0"
@@ -2260,6 +2346,12 @@ version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[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"
@@ -2690,6 +2782,17 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openapiv3"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8d427828b22ae1fff2833a03d8486c2c881367f1c336349f307f321e7f4d05"
dependencies = [
"indexmap",
"serde",
"serde_json",
]
[[package]]
name = "openssl-probe"
version = "0.2.1"
@@ -2731,6 +2834,12 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pastey"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
[[package]]
name = "pem"
version = "3.0.6"
@@ -2835,6 +2944,12 @@ 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"
@@ -2865,7 +2980,7 @@ dependencies = [
"log",
"lru 0.13.0",
"ntimestamp",
"reqwest",
"reqwest 0.12.28",
"self_cell",
"serde",
"sha1_smol",
@@ -3313,6 +3428,26 @@ dependencies = [
"bitflags 2.13.0",
]
[[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 = "regex"
version = "1.12.4"
@@ -3384,17 +3519,95 @@ dependencies = [
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"wasm-streams 0.4.2",
"web-sys",
"webpki-roots 1.0.8",
]
[[package]]
name = "reqwest"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
dependencies = [
"base64",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"js-sys",
"log",
"percent-encoding",
"pin-project-lite",
"serde",
"serde_json",
"sync_wrapper",
"tokio",
"tokio-util",
"tower",
"tower-http",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams 0.5.0",
"web-sys",
]
[[package]]
name = "reqwest-middleware"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc3f1384cffa4f274dad2d4ddd73aed32fed8f786d96c6be8aa4e5fd3c3b58"
dependencies = [
"anyhow",
"async-trait",
"http",
"reqwest 0.13.4",
"thiserror 2.0.18",
"tower-service",
]
[[package]]
name = "reqwest-retry"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe2412db2af7d2268e7a5406be0431f37d9eb67ff390f35b395716f5f06c2eaa"
dependencies = [
"anyhow",
"async-trait",
"futures",
"getrandom 0.2.17",
"http",
"hyper",
"reqwest 0.13.4",
"reqwest-middleware",
"retry-policies",
"thiserror 2.0.18",
"tokio",
"tracing",
"wasmtimer",
]
[[package]]
name = "resolv-conf"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7"
[[package]]
name = "retry-policies"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc05fbf560421a0357a750cbe78c7ca19d4923918490daabba313d5dbc871e47"
dependencies = [
"rand 0.10.1",
]
[[package]]
name = "ring"
version = "0.17.14"
@@ -3409,6 +3622,36 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rmcp"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1f571c72940a19d9532fe52dbea8bc9912bf1d766c2970bb824056b86f3f59"
dependencies = [
"async-trait",
"bytes",
"chrono",
"futures",
"http",
"http-body",
"http-body-util",
"pastey",
"pin-project-lite",
"rand 0.10.1",
"reqwest 0.13.4",
"schemars",
"serde",
"serde_json",
"sse-stream",
"thiserror 2.0.18",
"tokio",
"tokio-stream",
"tokio-util",
"tower-service",
"tracing",
"uuid",
]
[[package]]
name = "rustc-hash"
version = "2.1.2"
@@ -3608,6 +3851,32 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "schemars"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
dependencies = [
"chrono",
"dyn-clone",
"ref-cast",
"schemars_derive",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
@@ -3709,6 +3978,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_derive_internals"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.150"
@@ -3722,6 +4002,17 @@ dependencies = [
"zmij",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [
"itoa",
"serde",
"serde_core",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
@@ -3922,6 +4213,19 @@ dependencies = [
"der",
]
[[package]]
name = "sse-stream"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3962b63f038885f15bce2c6e02c0e7925c072f1ac86bb60fd44c5c6b762fb72"
dependencies = [
"bytes",
"futures-util",
"http-body",
"http-body-util",
"pin-project-lite",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -4222,6 +4526,18 @@ dependencies = [
"tokio-util",
]
[[package]]
name = "tokio-tungstenite"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.7.18"
@@ -4342,6 +4658,7 @@ dependencies = [
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
@@ -4442,6 +4759,22 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tungstenite"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
dependencies = [
"bytes",
"data-encoding",
"http",
"httparse",
"log",
"rand 0.9.4",
"sha1",
"thiserror 2.0.18",
]
[[package]]
name = "typenum"
version = "1.20.1"
@@ -4650,6 +4983,33 @@ dependencies = [
"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 = "wasmtimer"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b"
dependencies = [
"futures",
"js-sys",
"parking_lot",
"pin-utils",
"slab",
"wasm-bindgen",
]
[[package]]
name = "web-sys"
version = "0.3.102"

View File

@@ -3,6 +3,7 @@ members = [
"crates/alknet-vault",
"crates/alknet-core",
"crates/alknet-call",
"crates/alknet-http",
]
resolver = "2"

View File

@@ -0,0 +1,40 @@
[package]
name = "alknet-http"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "HTTP interface for alknet: serves HTTP/1.1 + HTTP/2 on standard ALPNs (with WebSocket upgrade for browser bidirectional access) and hosts the HTTP-backed call-protocol adapters"
repository.workspace = true
[lib]
name = "alknet_http"
[features]
default = ["h2", "http1"]
mcp = ["dep:rmcp"]
h2 = ["dep:hyper"]
http1 = ["dep:hyper"]
[dependencies]
alknet-core = { path = "../alknet-core" }
alknet-call = { path = "../alknet-call" }
axum = { version = "0.8", features = ["ws"] }
hyper = { version = "1", optional = true, features = ["server", "http1", "http2"] }
reqwest = { version = "0.13", default-features = false, features = ["json", "stream"] }
reqwest-middleware = "0.5"
reqwest-retry = "0.9"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
async-trait = "0.1"
tracing = "0.1"
thiserror = "2"
uuid = { version = "1", features = ["v4"] }
futures = "0.3"
openapiv3 = "2"
rmcp = { version = "1.8", optional = true, default-features = false, features = [
"client",
"server",
"transport-streamable-http-client-reqwest",
"transport-streamable-http-server",
] }

View File

@@ -0,0 +1,11 @@
//! HTTP-backed call-protocol adapters: `from_openapi`, `to_openapi`,
//! `from_mcp`, `to_mcp`.
//!
//! `from_openapi`/`from_mcp` are the no-env-vars credential injection point
//! (ADR-014); `to_openapi`/`to_mcp` are projections of the local registry
//! (ADR-017). `from_mcp`/`to_mcp` are feature-gated behind `mcp`
//! (streamable HTTP only — ADR-037). See
//! `docs/architecture/crates/http/http-adapters.md` and
//! `docs/architecture/crates/http/http-mcp.md`.
// TODO: implement

View File

@@ -0,0 +1,6 @@
//! Shared HTTP client (`ClientWithMiddleware`): reqwest + retry middleware
//! stack, used by `from_openapi`/`from_mcp` forwarding handlers.
//!
//! See `docs/architecture/crates/http/http-adapters.md` and OQ-40.
// TODO: implement

View File

@@ -0,0 +1,7 @@
//! Gateway: shared dispatch spine (`GatewayDispatch`) and error mapping.
//!
//! The 5 fixed gateway endpoints (`/search`, `/schema`, `/call`, `/batch`,
//! `/subscribe`) are the sole HTTP invoke path (ADR-042/047). See
//! `docs/architecture/crates/http/http-server.md`.
// TODO: implement

View File

@@ -0,0 +1,13 @@
//! alknet-http: HTTP interface for alknet — serves HTTP/1.1 + HTTP/2 on
//! standard ALPNs (with WebSocket upgrade for browser bidirectional access)
//! and hosts the HTTP-backed call-protocol adapters.
//!
//! Two roles in one crate (ADR-039): HTTP server (HttpAdapter, a
//! ProtocolHandler for h2/http1.1 + WS upgrade) and HTTP client host
//! (from_openapi/from_mcp forwarding, to_openapi/to_mcp projections).
pub mod adapters;
pub mod client;
pub mod gateway;
pub mod server;
pub mod websocket;

View File

@@ -0,0 +1,9 @@
//! HTTP server: `HttpAdapter`, axum-over-QUIC, gateway routes, `/healthz`,
//! decoy, and custom routes.
//!
//! Implements `alknet_core::types::ProtocolHandler` for the standard HTTP
//! ALPNs (`h2`, `http/1.1`) with WebSocket upgrade for browser
//! bidirectional access (ADR-044). See
//! `docs/architecture/crates/http/http-server.md`.
// TODO: implement

View File

@@ -0,0 +1,7 @@
//! WebSocket upgrade handler, framing, and dispatch handoff.
//!
//! WebSocket is the browser bidirectional path (ADR-044) and carries the
//! native `EventEnvelope` call-protocol session, not the gateway shape
//! (ADR-048). See `docs/architecture/crates/http/websocket.md`.
// TODO: implement