- bump alkcall 0.7 -> 0.8 (gateway feature unchanged). No code change
forced: alkcall 0.8.0 is additive on the call-plane JSON and the
registry seams (review 008's remediation — the establisher reply
projection, flavor-form open-op ids in discovery, the in-tree
ChannelRelay + hub-leg install template) and none of the new
surfaces are constructed in this crate: no Establishment reply
fields (the WS ferry passes Option<OpenEstablisher> through
unchanged), no marked specs imported through from_call (the from_wss
filter excludes the protocol-session ops), no ChannelRelay /
HubLegImports / HubLegTemplate consumption (hub-leg assembly stays
at the assembly layer)
- one ride-through on this crate's discovery surface: a deployment's
with_ws_openable_alpns open-op specs with non-standard names now
serve an explicit channel_open_alpn string through services/list +
services/schema (alkcall 0.8.0 U-1, ADR-047 amendment 3) so hubs
relaying via from_call reconstruct the marker; standard-shape names
stay byte-stable
Verification: cargo test 456 pass (default) / 589 (all-features),
clippy --all-targets -D warnings clean (default + all-features),
fmt --check clean, doc --no-deps clean
- 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)
- 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
- 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
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)
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
AGENTS.md, lib.rs, the README, and adapters/mod.rs docs all state
openapi is the shared spec model implied by both feature sides, and
the README's client row claims from_openapi under client — but the
feature graph only had server -> openapi. A lean client-only build
compiled yet silently lacked from_openapi (gated all(client,
openapi)).
Verification: cargo test (default + all-features), clippy both
feature sets -D warnings, fmt, publish --dry-run — all green.
alkcall 0.4.0 now enforces OperationSpec.input_schema at dispatch
(INVALID_INPUT). All 438+16 tests pass; the gateway path is
unaffected because alkhttp's imported ops validate through their own
CompiledInputSchema closure, which composes with the new registry
check (registry = raw JSON Schema semantics, adapter = closed by
default).
Bump alkcall 0.2 -> 0.3 (published 2026-09-04; the remediation of
alkcall reviews 004-005, the upstream resolution of alkhttp review 003
WS-24/WS-25). Two source-break classes, both mechanical:
- take_call_connection now returns Option<Arc<CallConnection>>
(was bare value) — drop the double-wrap in WssSession::connect.
- register/register_on/register_openable take &OperationRegistry
(was &mut) — drop 51 stale `mut` bindings (clippy --fix), which is
the interior-mutability change that makes the per-session fork
surface possible.
No behavior change in this crate yet; the 0.3 mechanisms (fork,
serve_single_stream, op/register, install_bootstrap_discovery,
collision policy) are the composition surface for alkhttp review 003
Unit 2 (WS-20..22, WS-26 wiring) — not wired here yet.
Verification: cargo test 453 passed (default) / 575 passed
(all-features), clippy both sides -D warnings clean, fmt clean,
cargo doc --no-deps clean.
- README covering the gateway surface, both import/export adapter
families, feature flags, and security posture (all claims verified
against the current code)
- standard MIT and Apache-2.0 license texts matching the
license = "MIT OR Apache-2.0" manifest field
- Cargo.toml: point the manifest at README.md and exclude scripts/
from the published package
Split the feature graph so consumers pulling only the import adapters
(from_openapi / from_jsonschema / from_mcp) no longer compile the axum
/ hyper server stack, and server-only deployments no longer compile
reqwest. One crate, one import path — sides cut by features, not by a
crate split.
Feature graph:
- server (default): axum host, gateway, WS upgrade, to_openapi, to_mcp
- client (default): client host, forward, from_jsonschema, from_openapi
- openapi: shared OpenAPISpec model (implied by both sides)
- mcp: from_mcp needs client, to_mcp needs server
- wss: tungstenite transport (from_wss); tungstenite half of the
shared WS↔byte-stream adapter
- h2/http1: hyper protocol features; imply server
Wire-contract neutral: gateway endpoints, ALPNs, and all public API
shapes unchanged; defaults keep both sides on.
Supporting changes:
- forward.rs drops its axum::body::Bytes type leak (bytes crate types)
- bounded_join + error-echo caps move to input_validation (usable by
both sides; openapi_spec no longer imports from forward)
- byte_adapter: axum flavor compiles under server, tungstenite under
wss; the generic pumps stay shared (WS-11)
- input_validation / openapi_spec import-only internals gated to the
side that consumes them
- http-body-util moves to dev-dependencies (was test-only)
- integration-test required-features updated for the new sides
- from_wss unit tests (axum producer harness) gated to server
Verified: cargo test (defaults, 453) and --all-features (575) pass;
lean side builds (client / server / client,mcp / client,wss /
server,wss / openapi-only) build clean with zero warnings;
clippy -D warnings clean across all feature combinations; fmt clean.
Bump the alkcall dependency to 0.2 (with the gateway feature) and
converge on the promoted shared pieces:
- The local dispatch spine (gateway/dispatch.rs, 721 lines) is deleted;
GatewayDispatch, schema_disclosure_denial, and DEFAULT_DEADLINE are
re-exported from alkcall::gateway (alkcall ADR-048). The 30 s default
deadline preserves the previous behavior exactly.
- gateway/schema_cache.rs (PublishSchemaCache) is deleted: alkcall CF-003
compiles publish_schema at registration time and exposes
OperationRegistry::publish_validator; the /publish chunk stream
resolves against it. Un-compilable schemas are now rejected at
registration, so the two end-to-end fail-closed tests were reworked
into a registration-rejection test (a stronger guarantee).
- schema_disclosure_denial consumers (to_mcp, routes) use alkcall's
promoted implementation; the alkhttp-local copy is gone (ADR-071
updated: the guard stays as defense-in-depth, the implementation no
longer forks).
- CF-001: from_wss drop monitor and the WS overlay tests use
CallError::connection_closed; the review-001-ws-eof-signal race tests
now assert retryable CONNECTION_CLOSED on both resolution paths (the
tolerated non-retryable INTERNAL write-failure outcome is gone).
- Added CHANGELOG.md (Keep a Changelog), Unreleased section records the
bump and convergence.
Verification: cargo test default 453 ok, wss 470 ok, mcp 526 ok,
all-features 575 ok; clippy -D warnings clean (default + all-features,
all-targets); fmt clean; cargo doc warning-free.
Net: -1093 lines.
- percent-encode path-parameter values with a WHATWG path-segment
superset (/, %, ?, #, \\, controls): traversal values, query/fragment
structure, and later-placeholder strings can no longer alter the
request line (FWD-01)
- single-pass template rendering; rendered values are never
re-substituted; unbound or unterminated placeholders error loudly
- append the request path to the base URL directory (https://host/v1
+ /chat/completions keeps /v1) instead of Url::join semantics,
with a post-assembly origin-equality check (FWD-02)
- base_url validation: https/http-only scheme allowlist, explicit
host required, userinfo rejected (credentials flow via
Capabilities only); request_path is never empty
Verification: cargo test (238 lib tests incl. 8 new FWD-01/02 tests),
cargo clippy --all-targets -- -D warnings, cargo fmt --check
The /mcp nest (to_mcp streamable HTTP service) collects the raw body
itself, so axum's extractor-based DefaultBodyLimit never applies and a
multi-GB chunked POST buffers entirely in memory (review-001 SRV-03).
Wrap the nest with an explicit counting-body middleware: 8 MiB cap
(headroom over the gateway's 2 MiB for JSON-RPC batch payloads),
Content-Length-declared oversizes rejected before reading, streaming
oversizes cut off mid-read and answered 413 (rmcp maps body-read errors
to 500, so the middleware sources the status itself).
Verification: cargo check (default + mcp + all-features); mcp test
suite pending tree unstuck from parallel agent's WIP.
- GW-01: /publish validates every NDJSON chunk against the op's
publish_schema (incl. the first-line chunk) via NdjsonChunkStream —
terminal Err(INVALID_INPUT)/422 on violation, matching the wire
dispatcher's per-chunk contract. Route-level fix; the alkcall spine
was explored and rejected (wire validation is pump-side by design).
- GW-06: the body is streamed, not buffered — Body::into_data_stream()
-> newline-framed BufferedLines -> lazily parsed chunk stream.
ADR-068 documents the streamed semantics and the 2 MiB per-line cap.
- GW-08: /batch capped at 100 operations (INVALID_INPUT 400).
- GW-09: internal-op batch entries now carry generated UUID request ids.
- GW-10: first publish line missing `chunk` is rejected INVALID_INPUT.
- GW-11: redundant /publish pre-checks removed; enforcement rides on
invoke_sink via the shared dispatch spine.
- HY-13: the vacuous stub test was replaced by a body-cut-short test.
- Adjacent: INVALID_OPERATION_TYPE now maps 422 (with identity) / 401
(without) in error.rs — the route relies on the shared mapper since
the pre-checks are gone (GW-03's finding; was a 500 fall-through).
Verification: cargo test 211 passed; cargo clippy --all-targets -- -D
warnings clean; cargo fmt --check clean.
Full-surface integration suite (tests/full_surface.rs, mcp feature):
- one HttpAdapter over real TCP (ProtocolHandler::handle path) serving
gateway endpoints, /openapi.json, /mcp, and the WS channels session
- gateway: search/schema/call/subscribe/batch/publish presence,
envelope shapes, error fidelity end-to-end
- from_openapi import -> Internal-by-default invisible from the wire ->
External facade composes it via env.invoke -> upstream HTTP API
called end-to-end (ADR-015 composition model exercised)
- to_openapi 6-path doc validated against openapiv3 over the wire
- to_mcp: MCP client connects to /mcp on the served adapter, lists the
4 gateway tools, search returns ACL-filtered ops (Sub excluded)
Production fix: the WS upgrade route was reserved but never wired into
HttpAdapter's router (the ws-upgrade-session tests built their own
router). Now wired with ws_bearer_auth (401 without a resolvable
token) around ws_upgrade_handler.
Docs sync: all 28 'Port notes' sections/blockquotes stripped from
ported ADRs/specs; OQ-01/OQ-02 statuses corrected to resolved in
overview.md, websocket.md, and the README table (open-questions.md was
already current).
Publish prep: cargo publish --dry-run --allow-dirty succeeds;
cargo doc --no-deps warning-free (ADR link targets fixed); feature
combinations (default / test-support / mcp / wss / all) compile
warning-free under clippy -D warnings.
Verified: cargo test (182 lib default), --all-features (227 lib + 29
integration), clippy -D warnings x3 feature sets, fmt, doc,
publish --dry-run.
Ported the alknet-http overlay verification to the channels-over-WS
session (tests/ws_overlay_ops.rs, test-support feature, 8 tests):
- overlay mechanism: browser-registered ops land in the connection's
Layer 2 overlay (register_imported), exposed via overlay_env() —
no PeerIds (browsers are not peers); PeerRef::Specific to a browser
id routes to nothing (NOT_FOUND)
- hub→browser call through compose_root_env's attached overlay
- AccessControl on browser ops gates hub calls (scope match allows,
missing scope FORBIDDEN)
- overlay dies with the connection; no leak between connections;
in-flight calls to browser ops resolve on close
- wire-level: 10 interleaved concurrent calls across two WS sessions
— no cross-correlation, no deadlock; disconnect mid-call resolves
and a fresh session works (no listener wedge)
byte_adapter: read_eof Notify now gated to the wss feature (its only
consumer is from_wss) so a test-support-only build is warning-free.
Verified: cargo test (182 lib), --all-features (227 lib + 5 MCP + 8
overlay + 10 WS integration), clippy -D warnings (default,
test-support, all-features), fmt.