6 Commits
Author SHA1 Message Date
glm-5.3-flash e854947c86 chore: release alkhttp 0.4.1
- version bump 0.4.0 -> 0.4.1 (patch: the MSRV raise is a metadata
  change that breaks no downstream able to build the crate before)
- README usage snippet 0.4 -> 0.4.1
- changelog: cut [0.4.1] with the alkcall 0.7.1 consumption + the
  rust-version 1.85 -> 1.88 floor raise under Changed

Verification: cargo publish --dry-run --allow-dirty (cargo test/clippy/
fmt green in the preceding deps commit)
2026-09-10 03:05:45 +00:00
glm-5.3-flash 660ccf3e76 chore(deps): consume alkcall 0.7.1; raise rust-version floor 1.85 -> 1.88
- the 1.85 claim was already false at the dependency level: the resolved
  lockfile pulls icu_* 2.x (MSRV 1.86 via jsonschema -> idna) and, since
  alkcall 0.7.1, alkcall itself declares 1.88 — 1.85 toolchains cannot
  build the tree regardless of what Cargo.toml declared
- raising the floor to 1.88 aligns with the ecosystem MSRV decision
  (noq QUIC path, per the alknet MSRV audit; recorded for alktls in
  OQ-TLS-08) and breaks no downstream that could build the crate before
- alkcall 0.7.1 rides in via the lockfile (version = "0.7" already
  covered it); no code change forced — 0.7.1 is its own MSRV raise plus
  the cf-006/cf-007 work consumed in the 0.7.0 wave
- one 1.88 clippy lint fixed: uninlined_format_args in a forward.rs test

Verification: 1.85 check fails as documented (icu_* 1.88 floors); 1.88
toolchain check/test/clippy --all-targets -D warnings clean; stable 1.94
test 456 (default) / 589 (all-features), clippy -D warnings (default +
all-features), fmt --check, doc --no-deps
2026-09-10 03:05:27 +00:00
glm-5.3-flash 8832160db1 chore: release alkhttp 0.4.0
- version bump 0.3.0 -> 0.4.0 (the CONNECTION_CLOSED -> 503 gateway
  mapping is a wire-visible behavior change for HTTP callers matching
  on the previously-emitted 500 — a minor bump, not a patch)
- README usage snippet 0.3 -> 0.4
- changelog: cut [0.4.0] with the alkcall 0.7.0 wave entry
  (CF-005/006/007, no code change forced) + the CONNECTION_CLOSED
  mapping under Changed (wire-surface behavior)

Verification: cargo test (456 passed), cargo test --all-features
(589 passed), clippy -D warnings (default + all-features), fmt
--check, cargo publish --dry-run --allow-dirty
2026-09-07 18:11:07 +00:00
glm-5.3-flash dbaaa4ec8c chore(deps): consume alkcall 0.7.0 — CONNECTION_CLOSED maps 503
Dependency wave + one wire-surface behavior fix:

- bump alkcall 0.6 -> 0.7 (gateway feature unchanged). No code change
  forced: this crate constructs no ServingConfig (the one 0.7.0
  struct-literal break — from_wss keeps the pure-consumer
  from_connection; opt-in serving remains the review-006 Part C
  deferred decision), and the CF-006 per-call opener-identity overlay
  is behavior-only upstream (hub-forwarded WS-ferry opens now resolve
  the end client's identity, the intended effect)
- gateway error table maps CONNECTION_CLOSED -> 503 Service
  Unavailable: alkcall 0.7.0's CF-007 amendment makes it the eighth
  protocol code (ADR-016's list is formal at eight); it previously
  fell to the catch-all 500, misreporting a retryable,
  provably-undelivered call as a permanent server failure. retryable:
  true, so the retry_after details path applies on 503. Tests pin the
  mapping and the Retry-After passthrough
- ADR-023 amended: the protocol-code list is eight (ALREADY_EXISTS +
  CONNECTION_CLOSED rows added to the §3 table, normative rule and
  call.error code list updated); http-adapters.md six-code references
  de-staled

Verification: cargo test (456 passed), cargo test --all-features
(589 passed), clippy -D warnings (default + all-features), fmt
--check, cargo doc --no-deps (0 warnings)
2026-09-07 18:01:36 +00:00
glm-5.3-flash 126fdec243 chore: release alkhttp 0.3.0
- version bump 0.2.0 -> 0.3.0 (the alkcall 0.6.0 consumption wave
  carries a compile-breaking change for downstream users of
  `OpenableAlpn::new`: handler closures gain the `_plan` parameter,
  so this release cannot be a patch)
- README usage snippet 0.2 -> 0.3
- changelog: cut [0.3.0] with the alkcall 0.6.0 wave entry
  (OpenHandler plan parameter, Establishment.plan threading,
  pump_bidi availability)

Verification: cargo test (454 passed), cargo test --all-features
(587 passed), clippy -D warnings (default + all-features),
cargo fmt --check, cargo doc --no-deps,
cargo publish --dry-run --allow-dirty
2026-09-07 09:37:38 +00:00
glm-5.3-flash a9429dfb1d chore(deps): consume alkcall 0.6.0 — OpenHandler gains the plan parameter
Mechanical pass for the alkcall 0.6.0 bump (review 007's
establishment follow-ups sweep: R-01 Establishment plan payload,
R-02 OpenHandler lifetime doc note, R-03 pump_bidi extraction):

- bump alkcall 0.5 -> 0.6 (gateway feature unchanged)
- the OpenHandler signature gained a plan parameter —
  Fn(Value, Option<ChannelPlan>, Connection, AuthContext) ->
  JoinHandle<()> — so the test's echo_open_handler closure gains
  `_plan` (the only closure-construction site in this crate)
- no ferry change: this crate constructs no Establishment and passes
  the Option<OpenEstablisher> through unchanged (OpenableAlpn fields
  and register_openable_with_establisher threading are unchanged in
  0.6.0); the establisher's Establishment.plan now reaches the pump
  handler's second parameter process-locally (ADR-049 amendment 2)
- docs updated: websocket.md (plan threading + pump_bidi pointer),
  OpenableAlpn field docs, with_ws_openable_alpns doc comment
- CHANGELOG [Unreleased] consumption-wave entry

Verification: cargo test (454 passed), cargo test --all-features
(587 passed), clippy -D warnings (default + all-features),
fmt --check, cargo doc --no-deps clean
2026-09-07 09:24:00 +00:00
12 changed files with 160 additions and 36 deletions
+72
View File
@@ -6,6 +6,78 @@ this crate adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
## [0.4.1] — 2026-09-10
### Changed
- **`rust-version` floor raised 1.85 → 1.88** (patch bump, no API change).
The 1.85 claim was already false at the dependency level: the resolved
lockfile pulls `icu_*` 2.x (MSRV 1.86 via `jsonschema``idna`) and —
since alkcall 0.7.1 — alkcall itself declares 1.88, so 1.85 toolchains
cannot build the tree regardless of what Cargo.toml declared. Raising
the floor to 1.88 aligns with the ecosystem MSRV decision (noq QUIC
path; recorded for alktls in OQ-TLS-08) and breaks no downstream that
could build the crate before. Verified: 1.88 toolchain `cargo test
--locked` + clippy `--all-targets -D warnings` clean; one 1.88 clippy
lint fixed (`uninlined_format_args` in a `forward.rs` test).
- **`alkcall` dependency consumed at 0.7.1** (lockfile bump; the
`version = "0.7"` requirement already covered it). No code change
forced — alkcall 0.7.1's changes are its own MSRV-floor raise plus the
cf-006/cf-007 feature work already consumed in the 0.7.0 wave.
## [0.4.0] — 2026-09-07
### Changed
- **`alkcall` dependency bumped to 0.7.0** (CF-005/006/007 — the
connect-side caller-identity seam + the downstream-findings sweep).
No code change in this crate: it constructs no `ServingConfig`
(the one struct-literal break — `from_wss` keeps the pure-consumer
`ChannelClient::from_connection`; opt-in serving remains the
review-006 Part C deferred decision) and the per-call opener-identity
overlay (CF-006) is behavior-only upstream — hub-forwarded opens on
the WS ferry now resolve the end client's identity instead of the
hub's, the intended effect. alkcall 0.7.0's ADR-016 amendment (the
protocol-code list is eight codes) resolves the upstream half of
review-006 Part C's doc-drift note.
### Changed (wire-surface behavior)
- **Gateway error table maps `CONNECTION_CLOSED` → 503 Service
Unavailable** (the alkcall 0.7.0 CF-007 amendment makes it the eighth
protocol code; ADR-023 amended). Previously it fell to the catch-all
500, which misreported a retryable, provably-undelivered call as a
permanent server failure. Reachable through the gateway when an
imported op's forwarding handler calls into a dropped transport
(`from_wss`'s pending-call fail-all is retryable
`CONNECTION_CLOSED`). The code is `retryable: true`, so the existing
`retry_after` details path applies on 503. Tests pin the mapping and
the `Retry-After` passthrough. Behavioral break for HTTP callers
matching on the 500 previously emitted for this code — hence a minor
bump, not a patch.
## [0.3.0] — 2026-09-07
### Changed
- **`alkcall` dependency bumped to 0.6.0** (review 007's
establishment follow-ups sweep). One consumer-visible change: the
`OpenHandler` signature gained a plan parameter —
`Fn(Value, Option<ChannelPlan>, Connection, AuthContext) ->
JoinHandle<()>` — so `OpenableAlpn::new` callers' handler closures
gain a `_plan` argument (mechanical). With an establisher attached
(ADR-049), its `Establishment.plan` (a typed-opaque
`Arc<dyn Any + Send + Sync>`) is threaded process-locally to the
handler's plan parameter: ALPN crates dial/allocate in the
establisher and deliver the live handle without a side-channel
handoff. This crate's WS ferry passes the `Option<OpenEstablisher>`
through unchanged and constructs no `Establishment` itself, so the
ride is otherwise additive — alkcall 0.6.0's `channels::pump_bidi`
helper (ADR-050) is available to data-plane handlers this crate
ferries. Docs updated (websocket.md, `OpenableAlpn` field docs,
adapter.rs).
## [0.2.0] — 2026-09-06
### Changed
Generated
+6 -6
View File
@@ -27,9 +27,9 @@ dependencies = [
[[package]]
name = "alkcall"
version = "0.5.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bbaeb718c370b74f9136d1d59b4608249bd7d1dd2332c0259f98351d709737f"
checksum = "ac26db919a1db9d72910ead8741af683bedefc625631028194b5f5e1dbd63cb6"
dependencies = [
"async-trait",
"bytes",
@@ -48,7 +48,7 @@ dependencies = [
[[package]]
name = "alkhttp"
version = "0.2.0"
version = "0.4.1"
dependencies = [
"alkcall",
"arc-swap",
@@ -1485,7 +1485,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -1860,7 +1860,7 @@ dependencies = [
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -2679,7 +2679,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
+3 -3
View File
@@ -1,8 +1,8 @@
[package]
name = "alkhttp"
version = "0.2.0"
version = "0.4.1"
edition = "2021"
rust-version = "1.85"
rust-version = "1.88"
license = "MIT OR Apache-2.0"
description = "HTTP interface for the alk stack: serves HTTP/1.1 + HTTP/2 on standard ALPNs (with WebSocket upgrade carrying the channels protocol) and hosts the HTTP-backed call-protocol adapters"
readme = "README.md"
@@ -42,7 +42,7 @@ h2 = ["server", "dep:hyper", "hyper-util/http2", "hyper/http2"]
http1 = ["server", "dep:hyper", "hyper-util/http1", "hyper/http1"]
[dependencies]
alkcall = { version = "0.5", features = ["gateway"] }
alkcall = { version = "0.7", features = ["gateway"] }
arc-swap = { version = "1", optional = true }
axum = { version = "0.8", optional = true, features = ["ws"] }
bytes = "1"
+1 -1
View File
@@ -161,7 +161,7 @@ A lean single-side build takes `default-features = false` plus the side
it needs:
```toml
alkhttp = { version = "0.2", default-features = false, features = ["server"] }
alkhttp = { version = "0.4.1", default-features = false, features = ["server"] }
```
## Security posture
@@ -4,21 +4,25 @@
## Status
Accepted (amended by alknet ADR-049 — protocol-level code list extended to six; alkcall ADR-021)
Accepted (amended by alknet ADR-049 — protocol-level code list extended to six; alkcall ADR-021; alkcall 0.7.0 CF-007 — the list is eight: `ALREADY_EXISTS` (alkcall ADR-022, mapped 409 Conflict by review 006 UP-01) and `CONNECTION_CLOSED` (alkcall ADR-016 CF-001, mapped 503 Service Unavailable in this crate's gateway error table))
## Context
The `OperationSpec` in the call crate (now alkcall) has `input_schema` and
`output_schema` but no `error_schemas`. The `call.error` payload (the alkcall
crate's `call-protocol.md`) carries a `code` and `message`, where `code` is
one of six infrastructure codes: `NOT_FOUND`, `FORBIDDEN`, `INVALID_INPUT`,
`INVALID_OPERATION_TYPE`, `INTERNAL`, `TIMEOUT`.
one of eight infrastructure codes: `NOT_FOUND`, `FORBIDDEN`, `INVALID_INPUT`,
`INVALID_OPERATION_TYPE`, `INTERNAL`, `TIMEOUT`, `ALREADY_EXISTS`,
`CONNECTION_CLOSED`.
These six codes cover **protocol-level failures** — the call protocol
These eight codes cover **protocol-level failures** — the call protocol
itself can always fail to find an operation, deny access, reject bad input,
reject the wrong dispatch method for the operation type, time out, or hit
an internal error. They are emitted by the dispatch machinery (the registry,
the adapter), not by operation handlers. `INVALID_OPERATION_TYPE` was added
reject the wrong dispatch method for the operation type, time out, hit an
internal error, reject an `op/register` collision (`ALREADY_EXISTS`, alkcall
ADR-022), or observe a provably-undelivered call (`CONNECTION_CLOSED`,
alkcall ADR-016 CF-001 — the only retryable protocol code). They are emitted
by the dispatch machinery (the registry, the adapter), not by operation
handlers. `INVALID_OPERATION_TYPE` was added
by alknet ADR-049 (streaming handler for subscriptions — now alkcall ADR-021;
`invoke()` called on a `Sub`, or `invoke_streaming()` on a `Query`/`Mutation`).
@@ -173,8 +177,8 @@ optional-array convention.
- `code` — the error code. Either a protocol-level code (`NOT_FOUND`,
`FORBIDDEN`, `INVALID_INPUT`, `INVALID_OPERATION_TYPE`, `INTERNAL`,
`TIMEOUT`) or an operation-level domain code from `error_schemas` (e.g.,
`FILE_NOT_FOUND`, `RATE_LIMITED`).
`TIMEOUT`, `ALREADY_EXISTS`, `CONNECTION_CLOSED`) or an operation-level
domain code from `error_schemas` (e.g., `FILE_NOT_FOUND`, `RATE_LIMITED`).
- `message` — human-readable error message. Unstructured — for logging and
debugging, not for programmatic handling. Consumers should switch on
`code`, not parse `message`.
@@ -190,8 +194,8 @@ optional-array convention.
### 3. Protocol-level vs operation-level error codes
The six existing codes are **protocol-level** — emitted by the dispatch
machinery, not by handlers:
The eight protocol-level codes are **protocol-level** — emitted by the
dispatch machinery, not by handlers:
| Code | Emitted by | Meaning |
|------|-----------|---------|
@@ -201,6 +205,8 @@ machinery, not by handlers:
| `INVALID_OPERATION_TYPE` | Registry / `OperationEnv` | Wrong dispatch path for the operation's type (`invoke()` on a `Sub`, `invoke_streaming()` on a `Query`/`Mutation`, `invoke_sink()` on a `Query`/`Mutation`/`Sub`, or `OperationEnv::invoke()` on a `Sub` during composition — alkcall ADR-021; `Pub` ops dispatch via `invoke_sink()`, alkcall ADR-046) |
| `INTERNAL` | Registry / Adapter | Handler panic, unhandled error, connection failure |
| `TIMEOUT` | Adapter | Request timed out |
| `ALREADY_EXISTS` | Registry / collision gate | `op/register` collision — a peer-announced op may not replace the serving side's own registrations (alkcall ADR-022 G-03) |
| `CONNECTION_CLOSED` | Client write path | The `call.requested` frame could not be written — the call is provably undelivered (alkcall ADR-016 CF-001). `retryable: true` — the only protocol code a caller may auto-retry. |
Operation-level domain codes are emitted by **handlers** — the operation's
own logic determines what went wrong. They are declared in `error_schemas`
@@ -251,9 +257,9 @@ accordingly.
```
**Normative rule (review #002 W20)**: `from_openapi` must not produce error
codes that collide with the six protocol-level codes (`NOT_FOUND`,
codes that collide with the protocol-level codes (`NOT_FOUND`,
`FORBIDDEN`, `INVALID_INPUT`, `INVALID_OPERATION_TYPE`, `INTERNAL`,
`TIMEOUT`). The adapter prefixes
`TIMEOUT`, `ALREADY_EXISTS`, `CONNECTION_CLOSED`). The adapter prefixes
imported error codes with `HTTP_` and the status number (e.g., `HTTP_404`,
`HTTP_429`) to avoid collision. This is a requirement for the adapter, not
a naming convention — the `from_openapi` example above was previously shown
+4 -3
View File
@@ -553,8 +553,9 @@ for the factoring recommendation (thin shared struct, not a trait).
`from_openapi` maps OpenAPI non-2xx response status codes to
`ErrorDefinition`s (alkcall ADR-016 §5). The normative rule (review
#002 W20): `from_openapi` must not produce error codes that collide
with the six protocol-level codes (`NOT_FOUND`, `FORBIDDEN`,
`INVALID_INPUT`, `INVALID_OPERATION_TYPE`, `INTERNAL`, `TIMEOUT`). The
with the protocol-level codes (`NOT_FOUND`, `FORBIDDEN`,
`INVALID_INPUT`, `INVALID_OPERATION_TYPE`, `INTERNAL`, `TIMEOUT`,
`ALREADY_EXISTS`, `CONNECTION_CLOSED`). The
adapter prefixes imported error codes with `HTTP_` and the status
number:
@@ -601,7 +602,7 @@ request-level cap failure (422; GW-16 unified it with the
`INVALID_INPUT → 422` mapping — it was hand-rolled as 400 before
review-002). `BatchResultEntry.error` references
the `BatchError` component (review-002 PRJ-16b): the serialized
`CallError` as a oneOf over the six protocol-code envelopes plus a
`CallError` as a oneOf over the protocol-code envelopes plus a
generic arm carrying the operation-declared codes. See alkcall ADR-016.
## Why
+9 -1
View File
@@ -285,7 +285,15 @@ semantically-validating hook dials/prepares the backend before the
reply, and a bounded failure resolves `channel:open_failed` with
`details.reason` (the channel never exists consumer-side). The
per-registration timeout override bounds the establisher when the
dispatch carries no deadline. The `OpenableAlpns` request-extension
dispatch carries no deadline. The establisher's `Establishment.plan`
payload (alkcall 0.6.0 / ADR-049 amendment 2 — a typed-opaque
`ChannelPlan`) is threaded process-locally to the pump handler's
second parameter: the establisher and the handler agree on the
concrete type, so ALPN crates dial/allocate in the establisher and
deliver the live handle to their handler without a side-channel
handoff. Data-plane handlers that pump a channel stream against a
peer's split halves can use alkcall's `channels::pump_bidi` helper
(alkcall 0.6.0 / ADR-050). The `OpenableAlpns` request-extension
fallback is available for bare-registry/custom
upgrade routes. Cap policy is the `ChannelsPolicy` extension (one
instance consulted by both the open wrappers and the demux teardown).
+1 -2
View File
@@ -2125,8 +2125,7 @@ mod tests {
);
assert!(
!segments.iter().any(|s| s == "." || s == ".."),
"value `{value:?}` must not leave lone dot segments: {:?}",
segments
"value `{value:?}` must not leave lone dot segments: {segments:?}"
);
}
Err(err) => {
+27 -3
View File
@@ -4,9 +4,11 @@
//! (`NOT_FOUND`, `FORBIDDEN`, `INVALID_INPUT`, `INVALID_OPERATION_TYPE`,
//! `TIMEOUT`, `ALREADY_EXISTS` — the seventh code, alkcall ADR-022's
//! `op/register` collision policy, mapped 409 Conflict, review-006
//! UP-01) map to fixed statuses; operation-level codes imported from
//! external HTTP APIs are prefixed `HTTP_<status>` and map to their
//! declared status.
//! UP-01; `CONNECTION_CLOSED` — the eighth code, alkcall ADR-016's
//! retryable undelivered-call code, mapped 503 Service Unavailable,
//! alkcall 0.7.0's CF-007 amendment made the list formal) map to fixed
//! statuses; operation-level codes imported from external HTTP APIs are
//! prefixed `HTTP_<status>` and map to their declared status.
//!
//! The identity-aware variant maps the ambiguous protocol codes
//! (`FORBIDDEN`, `INVALID_OPERATION_TYPE`) to `401` when no token
@@ -30,6 +32,7 @@ const PROTOCOL_CODE_INVALID_INPUT: &str = "INVALID_INPUT";
const PROTOCOL_CODE_INVALID_OPERATION_TYPE: &str = "INVALID_OPERATION_TYPE";
const PROTOCOL_CODE_TIMEOUT: &str = "TIMEOUT";
const PROTOCOL_CODE_ALREADY_EXISTS: &str = "ALREADY_EXISTS";
const PROTOCOL_CODE_CONNECTION_CLOSED: &str = "CONNECTION_CLOSED";
const PROTOCOL_CODE_INTERNAL: &str = "INTERNAL";
const HTTP_PREFIX: &str = "HTTP_";
@@ -40,6 +43,7 @@ const STATUS_FORBIDDEN: u16 = 403;
const STATUS_UNPROCESSABLE: u16 = 422;
const STATUS_TIMEOUT: u16 = 504;
const STATUS_CONFLICT: u16 = 409;
const STATUS_SERVICE_UNAVAILABLE: u16 = 503;
const STATUS_INTERNAL: u16 = 500;
const RETRY_AFTER_STATUSES: &[u16] = &[429, 503];
@@ -77,6 +81,7 @@ pub fn call_error_to_http_status_with_identity(
}
PROTOCOL_CODE_TIMEOUT => STATUS_TIMEOUT,
PROTOCOL_CODE_ALREADY_EXISTS => STATUS_CONFLICT,
PROTOCOL_CODE_CONNECTION_CLOSED => STATUS_SERVICE_UNAVAILABLE,
PROTOCOL_CODE_INTERNAL => STATUS_INTERNAL,
code if code.starts_with(HTTP_PREFIX) => code[HTTP_PREFIX.len()..]
.parse::<u16>()
@@ -193,6 +198,25 @@ mod tests {
assert_eq!(call_error_to_http_status(&error), 409);
}
#[test]
fn connection_closed_maps_to_503() {
let error = CallError::connection_closed("undelivered");
assert_eq!(call_error_to_http_status(&error), 503);
}
#[test]
fn connection_closed_carries_retry_after_when_details_present() {
let error = CallError::connection_closed("undelivered")
.with_details(serde_json::json!({ "retry_after": "5" }));
let resp = call_error_to_http_response(&error);
assert_eq!(resp.status(), 503);
let retry_after = resp
.headers()
.get(header::RETRY_AFTER)
.map(|v| v.to_str().unwrap().to_string());
assert_eq!(retry_after.as_deref(), Some("5"));
}
#[test]
fn internal_maps_to_500() {
let error = CallError::internal("boom");
+4 -1
View File
@@ -273,7 +273,10 @@ impl HttpAdapter {
/// `channel_open` marker), the ALPN-specific
/// [`OpenHandler`](alkcall::channels::operations::OpenHandler),
/// and the optional establisher + per-registration timeout
/// (ADR-049, threaded through with `None` defaults). Each WS
/// (ADR-049, threaded through with `None` defaults). With an
/// establisher attached, its `Establishment.plan` (alkcall 0.6.0 /
/// ADR-049 amendment 2) is threaded process-locally to the pump
/// handler's second parameter. Each WS
/// session's per-session fork registers the set (plus the generic
/// channel ops, bootstrap discovery, and `op/register`), so a WS
/// client can open data channels exactly as any channels consumer
+13 -2
View File
@@ -271,13 +271,24 @@ pub struct OpenableAlpn {
/// per the upstream C-08 stub until channel adoption lands).
pub spec: OperationSpec,
/// The data-plane protocol handler spawned on the allocated
/// channel's `Connection`.
/// channel's `Connection` — `Fn(Value, Option<ChannelPlan>,
/// Connection, AuthContext) -> JoinHandle<()>`. With an
/// establisher attached, the plan (alkcall 0.6.0 /
/// ADR-049 amendment 2) is the establisher's `Establishment.plan`:
/// the establisher and the handler agree on the concrete type
/// (downcast in the ALPN crate); `None` when no establisher is
/// registered or it returned `Establishment::default()`
/// (`alkcall::channels::operations::Establishment::default`).
pub open_handler: OpenHandler,
/// The awaited establishment phase (ADR-049 §1): validate params
/// semantically, consult ownership, prepare/dial the backend —
/// before the open reply. `None` (the default) = an always-OK
/// establisher (the pre-ADR-049 shape; existing registrations
/// behave unchanged).
/// behave unchanged). A successful establisher returns
/// `Establishment::new(plan)` (to deliver a channel plan to the
/// pump handler) or `Establishment::default()` when it only
/// validates — both in
/// `alkcall::channels::operations`.
pub establisher: Option<OpenEstablisher>,
/// The per-registration bound on the establisher await
/// (ADR-049 §2). `None` = [`ESTABLISHMENT_TIMEOUT`] (10s) when the
+1 -1
View File
@@ -1057,7 +1057,7 @@ use alkcall::channels::operations::OpenHandler;
/// payload) chunks; the handler reads the channel's BiStream and
/// writes the echo — the exact data-plane shape ADR-067 promises.
fn echo_open_handler() -> OpenHandler {
Arc::new(move |_input, channel_conn, _auth| {
Arc::new(move |_input, _plan, channel_conn, _auth| {
tokio::spawn(async move {
let mut stream = match channel_conn.accept_bi().await {
Ok(s) => s,