Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
449661eb87 | ||
|
|
c89aa65fb2 | ||
|
|
2cf0dc7bea |
No files matched your search
@@ -4,6 +4,44 @@ All notable changes to this crate are documented here. The format is
|
|||||||
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
||||||
this crate adheres to [Semantic Versioning](https://semver.org/).
|
this crate adheres to [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
## [0.7.0] — 2026-10-14
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **`alkcall` dependency bumped to 0.9.0** (the stub-sweep release: the
|
||||||
|
four registered-but-always-failing stubs across nine published
|
||||||
|
versions are replaced with real implementations — the marked-pub
|
||||||
|
open contract (S-01), `channel/control` (S-02),
|
||||||
|
`channel/resources/subscribe` (S-03), and `op/register`
|
||||||
|
forward-through (S-04)). No code change in this crate — none of the
|
||||||
|
0.9.0 breaking surfaces are constructed or pattern-matched here: no
|
||||||
|
`ManagerError` match arms (the new `InvalidAdopt` variant changes
|
||||||
|
nothing), no `RelayError` matching (the removed `PubTypedOpen`
|
||||||
|
variant is unreachable from this crate), no `Establishment`
|
||||||
|
construction or `Debug` dependence (the WS ferry passes
|
||||||
|
`Option<OpenEstablisher>` through unchanged), and the
|
||||||
|
`op/register` forward-through refactor does not touch the
|
||||||
|
`from_wss` import filter or the adapter-registered leaf bundles.
|
||||||
|
The S-01 marked-pub machinery is consumer-side assembly, not an
|
||||||
|
HTTP-surface concern; the four gateway operations and the WS
|
||||||
|
session shape are unchanged.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `tests/ws_overlay_ops.rs` now expects `register_imported`'s new
|
||||||
|
`Result<(), String>` return (alkcall 0.9.0 API change): the eight
|
||||||
|
connection-overlay registration sites assert success instead of
|
||||||
|
discarding the value. Test-only.
|
||||||
|
- `fuzz/shared` follows the main crate to alkcall 0.9 (the harness
|
||||||
|
replay previously resolved alkcall 0.8.1 alongside alkhttp's 0.9.0,
|
||||||
|
two incompatible copies in one build). Infra-only.
|
||||||
|
|
||||||
|
Minor bump 0.6.0 → 0.7.0 per the dep-wave convention (0.3.0 rode
|
||||||
|
alkcall 0.6.0, 0.4.0 rode 0.7.0, 0.5.0 rode 0.8.0): this crate's
|
||||||
|
public API carries alkcall types through re-exports and the
|
||||||
|
`ProtocolHandler` impl, so a semver-breaking upstream is
|
||||||
|
semver-relevant here.
|
||||||
|
|
||||||
## [0.6.0] — 2026-09-29
|
## [0.6.0] — 2026-09-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Generated
+3
-3
@@ -27,9 +27,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkcall"
|
name = "alkcall"
|
||||||
version = "0.8.1"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf6af1e4af1460480849adf959c972d65deeafc36f4101064ced1ce6d1adfd5b"
|
checksum = "a3562f1f7b348cdeb3d9181eaf57b0a2fb3f988d4280e8e225dadfd7f763cb84"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -48,7 +48,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkhttp"
|
name = "alkhttp"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alkcall",
|
"alkcall",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "alkhttp"
|
name = "alkhttp"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.88"
|
rust-version = "1.88"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
@@ -46,7 +46,7 @@ h2 = ["server", "dep:hyper", "hyper-util/http2", "hyper/http2"]
|
|||||||
http1 = ["server", "dep:hyper", "hyper-util/http1", "hyper/http1"]
|
http1 = ["server", "dep:hyper", "hyper-util/http1", "hyper/http1"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
alkcall = { version = "0.8.1", features = ["gateway"] }
|
alkcall = { version = "0.9", features = ["gateway"] }
|
||||||
arc-swap = { version = "1", optional = true }
|
arc-swap = { version = "1", optional = true }
|
||||||
axum = { version = "0.8", optional = true, features = ["ws"] }
|
axum = { version = "0.8", optional = true, features = ["ws"] }
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ A lean single-side build takes `default-features = false` plus the side
|
|||||||
it needs:
|
it needs:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
alkhttp = { version = "0.5.0", default-features = false, features = ["server"] }
|
alkhttp = { version = "0.7.0", default-features = false, features = ["server"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security posture
|
## Security posture
|
||||||
|
|||||||
Generated
+5
-5
@@ -27,9 +27,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkcall"
|
name = "alkcall"
|
||||||
version = "0.8.1"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf6af1e4af1460480849adf959c972d65deeafc36f4101064ced1ce6d1adfd5b"
|
checksum = "a3562f1f7b348cdeb3d9181eaf57b0a2fb3f988d4280e8e225dadfd7f763cb84"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1405,7 +1405,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1756,7 +1756,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2513,7 +2513,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ mcp = ["alkhttp/mcp"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
alkhttp = { path = "../.." }
|
alkhttp = { path = "../.." }
|
||||||
alkcall = "0.8.1"
|
alkcall = "0.9"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ impl FromOpenAPI {
|
|||||||
`paths` for this path's `parameters` (and the path-item's shared \
|
`paths` for this path's `parameters` (and the path-item's shared \
|
||||||
list) has `name` and `in`, and that its $ref, if any, resolves. \
|
list) has `name` and `in`, and that its $ref, if any, resolves. \
|
||||||
The placeholder would otherwise render as a literal `{{}}` path segment",
|
The placeholder would otherwise render as a literal `{{}}` path segment",
|
||||||
bounded_join(&[path_template.to_string()]),
|
bounded_join(std::slice::from_ref(&path_template)),
|
||||||
bounded_join(&unbound)
|
bounded_join(&unbound)
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -267,14 +267,17 @@ impl WsSessions {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct OpenableAlpn {
|
pub struct OpenableAlpn {
|
||||||
/// The open-op spec (Query/Mutation/Sub with the `channel_open`
|
/// The open-op spec (Query/Mutation/Sub with the `channel_open`
|
||||||
/// marker; a `Pub` open op resolves `channel:pub_open_not_implemented`
|
/// marker). A `Pub`-typed marked spec is refused loudly at
|
||||||
/// per the upstream C-08 stub until channel adoption lands).
|
/// registration by the upstream openable path (marked pub
|
||||||
|
/// openables register via alkcall's
|
||||||
|
/// `ChannelCore::register_pub_openable`, which this WS fork
|
||||||
|
/// wrapper does not thread yet).
|
||||||
pub spec: OperationSpec,
|
pub spec: OperationSpec,
|
||||||
/// The data-plane protocol handler spawned on the allocated
|
/// The data-plane protocol handler spawned on the allocated
|
||||||
/// channel's `Connection` — `Fn(Value, Option<ChannelPlan>,
|
/// channel's `Connection` — `Fn(Value, Option<ChannelPlan>,
|
||||||
/// Connection, AuthContext) -> JoinHandle<()>`. With an
|
/// Connection, AuthContext) -> JoinHandle<()>`. With an
|
||||||
/// establisher attached, the plan (alkcall 0.6.0 /
|
/// establisher attached, the plan (alkcall ADR-049
|
||||||
/// ADR-049 amendment 2) is the establisher's `Establishment.plan`:
|
/// amendment 2) is the establisher's `Establishment.plan`:
|
||||||
/// the establisher and the handler agree on the concrete type
|
/// the establisher and the handler agree on the concrete type
|
||||||
/// (downcast in the ALPN crate); `None` when no establisher is
|
/// (downcast in the ALPN crate); `None` when no establisher is
|
||||||
/// registered or it returned `Establishment::default()`
|
/// registered or it returned `Establishment::default()`
|
||||||
|
|||||||
+19
-8
@@ -212,7 +212,8 @@ async fn browser_registered_op_lands_in_overlay_not_peer_composite() {
|
|||||||
let overlay_env = conn.overlay_env();
|
let overlay_env = conn.overlay_env();
|
||||||
assert!(!overlay_env.contains("ui/dragged"));
|
assert!(!overlay_env.contains("ui/dragged"));
|
||||||
|
|
||||||
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
assert!(overlay_env.contains("ui/dragged"));
|
assert!(overlay_env.contains("ui/dragged"));
|
||||||
assert!(
|
assert!(
|
||||||
overlay_env.peer_ids().is_empty(),
|
overlay_env.peer_ids().is_empty(),
|
||||||
@@ -226,7 +227,8 @@ async fn hub_call_reaches_browser_op_through_overlay_env() {
|
|||||||
let dp = dispatcher(registry, provider_with(vec![]));
|
let dp = dispatcher(registry, provider_with(vec![]));
|
||||||
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
||||||
|
|
||||||
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
|
|
||||||
let ctx = hub_root_context(
|
let ctx = hub_root_context(
|
||||||
"hub-call-1",
|
"hub-call-1",
|
||||||
@@ -257,7 +259,8 @@ async fn peerref_specific_browser_x_routes_to_nothing() {
|
|||||||
let registry = echo_registry();
|
let registry = echo_registry();
|
||||||
let dp = dispatcher(registry, provider_with(vec![]));
|
let dp = dispatcher(registry, provider_with(vec![]));
|
||||||
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
||||||
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
|
|
||||||
let composed_env = dp.compose_root_env(
|
let composed_env = dp.compose_root_env(
|
||||||
&conn,
|
&conn,
|
||||||
@@ -300,7 +303,8 @@ async fn access_control_on_browser_op_gates_hub_call() {
|
|||||||
required_scopes: vec!["ui:write".to_string()],
|
required_scopes: vec!["ui:write".to_string()],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
));
|
))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
let env = conn.overlay_env();
|
let env = conn.overlay_env();
|
||||||
let ctx = hub_root_context(
|
let ctx = hub_root_context(
|
||||||
"hub-acl-ok",
|
"hub-acl-ok",
|
||||||
@@ -332,7 +336,9 @@ async fn access_control_on_browser_op_gates_hub_call() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn overlay_dropped_on_disconnect_no_leak_between_connections() {
|
async fn overlay_dropped_on_disconnect_no_leak_between_connections() {
|
||||||
let conn1 = CallConnection::new_overlay_only(identity("browser-1", &[]));
|
let conn1 = CallConnection::new_overlay_only(identity("browser-1", &[]));
|
||||||
conn1.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn1
|
||||||
|
.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
assert!(conn1.overlay_env().contains("ui/dragged"));
|
assert!(conn1.overlay_env().contains("ui/dragged"));
|
||||||
drop(conn1);
|
drop(conn1);
|
||||||
|
|
||||||
@@ -345,8 +351,12 @@ async fn overlay_dropped_on_disconnect_no_leak_between_connections() {
|
|||||||
// Connection-local isolation: each session's overlay is its own.
|
// Connection-local isolation: each session's overlay is its own.
|
||||||
let conn_a = CallConnection::new_overlay_only(identity("browser-a", &[]));
|
let conn_a = CallConnection::new_overlay_only(identity("browser-a", &[]));
|
||||||
let conn_b = CallConnection::new_overlay_only(identity("browser-b", &[]));
|
let conn_b = CallConnection::new_overlay_only(identity("browser-b", &[]));
|
||||||
conn_a.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn_a
|
||||||
conn_b.register_imported(browser_registration("ui/click", AccessControl::default()));
|
.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
|
conn_b
|
||||||
|
.register_imported(browser_registration("ui/click", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
assert!(conn_a.overlay_env().contains("ui/dragged"));
|
assert!(conn_a.overlay_env().contains("ui/dragged"));
|
||||||
assert!(!conn_a.overlay_env().contains("ui/click"));
|
assert!(!conn_a.overlay_env().contains("ui/click"));
|
||||||
assert!(conn_b.overlay_env().contains("ui/click"));
|
assert!(conn_b.overlay_env().contains("ui/click"));
|
||||||
@@ -356,7 +366,8 @@ async fn overlay_dropped_on_disconnect_no_leak_between_connections() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ws_close_mid_call_to_browser_op_aborts_call() {
|
async fn ws_close_mid_call_to_browser_op_aborts_call() {
|
||||||
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
let conn = Arc::new(CallConnection::new_overlay_only(identity("browser", &[])));
|
||||||
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()));
|
conn.register_imported(browser_registration("ui/dragged", AccessControl::default()))
|
||||||
|
.expect("register_imported must accept the unmarked spec");
|
||||||
|
|
||||||
let rx = {
|
let rx = {
|
||||||
let mut pending = conn.pending().lock();
|
let mut pending = conn.pending().lock();
|
||||||
|
|||||||
Reference in new issue
Block a user