Commit Graph
65 Commits
Author SHA1 Message Date
glm-5.3-flash 91483a74b4 docs: missing_docs sweep — 0 warnings + deny gate + publish-prep decisions (HY-02, HY-04, HY-11)
- document every public-API item across 18 files (openapi_spec model,
  HttpAuthScheme/HttpServiceConfig, HttpClientBuildError + SharedHttpClient
  accessors, RetryAfterMiddleware, GatewayDispatch, gateway error
  mapping, CallRequest/SchemaQuery/SubscribeStream, HttpAdapter +
  ALPNs + builders, decoy/healthz/state, WsSessions/WsPumps,
  from_openapi/from_jsonschema/from_mcp/from_wss/to_mcp, lib.rs module
  docs)
- enforcement: #![deny(missing_docs)] at crate root — stronger than CI
  rustdocflags (every build incl. cfg(test), where rustdoc misses the
  test-support module docs)
- HY-10 (opportunistic): all 8 docs.rs/alkhttp placeholder ADR links +
  the one relative ../docs link converted to plain text; the 10
  pre-existing private/redundant intra-doc-link warnings fixed —
  RUSTDOCFLAGS="-D warnings" cargo doc is fully clean
- HY-11 decision: docs/ + tasks/ excluded from the published package
  (contributor-facing design/process material; ADR references degrade
  to plain text uniformly). cargo publish --dry-run: 38 files, ~889 KiB,
  zero docs/ or tasks/ entries
- HY-04 decision: keep + document — frame_channel0_chunk's unwrap is
  on serializing the acyclic EventEnvelope (unreachable failure);
  # Panics on it and the adjacent WsClient senders state the contract

Verified: cargo test (299 + 5 TLS), --all-features (370 + suites),
--no-default-features (299), clippy --all-targets -D warnings
(default + all-features), fmt --check, cargo doc -D warnings clean,
cargo publish --dry-run --allow-dirty clean.

Tasks: review-001-missing-docs-sweep (final pending task; 42/42)
2026-08-30 08:25:18 +00:00
glm-5.3-flash 7ce1ca6fbd feat(adapters): loud unsupported-OpenAPI-feature handling (OAI-06)
- build_error_schemas: default/wildcard response keys dropped with a
  warn instead of emitting a dead HTTP_0 ErrorDefinition — /search
  never advertises a code that can't match (the runtime mapper already
  synthesizes HTTP_<actual> for unmapped statuses)
- check_parameter_style: non-default style/explode parameter forms
  (spaceDelimited, pipeDelimited, deepObject, form+explode:false,
  simple+explode:true) fail import with a feature-naming SchemaParse;
  wire-equivalent defaults (form, simple) import unchanged — no more
  silent "[1,2]" array mis-serialization
- servers overrides rejected at import at all three levels (document,
  path, operation) — the adapter pins one base_url at assembly time
- trace-only paths: skip is now logged (warn naming path + methods),
  documented-as-inert instead of silent
- detect_op_type + build_output_schema sweep 2XX/default keys for
  text/event-stream — a default-declared SSE stream classifies as Sub
  instead of returning one giant text body

Tests: 11 new (error-drop, style rejections + default accept, servers
3-level rejections + baseline, trace skip, SSE default/2XX detection).
Verified: cargo test (299), --all-features (370 + suites), clippy
--all-targets -D warnings (default + all-features), fmt --check.

Tasks: review-001-openapi-loud-degradation
2026-08-30 08:10:40 +00:00
glm-5.3-flash edbda6605b refactor(client): owned RetryConfig + TLS/mTLS test coverage (HY-06, COV-02)
- HttpClientConfig.retry_policy: ExponentialBackoff (semver anchor to a
  reqwest-retry concrete type) replaced by retry: RetryConfig — an
  owned struct of plain scalars (max_retries, initial_backoff,
  max_retry_interval, defaults matching the previous backoff exactly);
  the ExponentialBackoff policy is built internally by the middleware
  stack; no reqwest_retry type is public anymore
- ClientCertConfig fields documented (none had docs)
- new tests/client_tls.rs: per-test rcgen private PKI + tokio-rustls
  HTTPS server; drives the real SharedHttpClient through
  HttpClientConfig file paths — CA-bundle success path, private-roots
  rejection (source-chain assertion: invalid peer certificate),
  mTLS end-to-end with client identity, mTLS rejection without
  identity, and reload-to-CA-bundle interplay
- dev-deps: rcgen 0.14, tokio-rustls 0.26, rustls 0.23 (aws_lc_rs),
  rustls-pki-types 1, uuid

Verified: cargo test (288 + 5 TLS), --all-features (359 + suites),
--no-default-features (288; pre-existing warnings only), clippy
--all-targets -D warnings (default + all-features), fmt --check,
cargo doc --no-deps.

Tasks: review-001-client-config-and-cert-coverage
2026-08-30 07:24:34 +00:00
glm-5.3-flash 1572a9d2d0 fix(gateway): fail-closed publish_schema compile + compile-once cache (GW-01 follow-up)
- new gateway::schema_cache — PublishSchemaCache: compile the op's
  publish_schema once per registration (value-keyed invalidation for
  hot reload), cache compile failures (logged once at error level,
  never retried per request)
- /publish compile failure is now fail-closed: the chunk stream
  terminates with INTERNAL (500), the error text stays in the log
  (no schema internals on the wire) — the per-request warn-and-skip
  unvalidated ingest path is removed
- schema resolution is lazy (first chunk poll, after invoke_sink's
  404/403/422 pre-checks — GW-11 order preserved) and keyed by schema
  value, so re-registration/hot reload is picked up (test)
- NdjsonChunkStream: first Err item is terminal (done + stream end),
  mirroring the wire pump's send(Err) + break — Ok chunks can never
  follow an error on the HTTP path either (found by spy-handler test)

Verified: cargo test (308), cargo test --all-features, clippy
--all-targets -D warnings (default + all-features), fmt --check.

Tasks: review-001-publish-schema-validation-robust
2026-08-30 07:02:27 +00:00
glm-5.3-flash 5d6945cd4b docs(tasks): post-remediation sweep — 4 follow-up tasks
Found in the sweep of completed review-001 remediation:
- /publish schema validation fails open on compile error + recompiles
  per request (remediation-introduced, routes.rs:254-268)
- OAI-06 loud-degradation unblocked and still open (HTTP_0 marker)
- HY-06 ExponentialBackoff in public API + COV-02 mTLS success path
  both unblocked post client-config rework
- HY-02/04/11 publish-prep docs gate (104 missing-docs warnings
  re-measured)

Also flagged, not tasked here: WS-12 (alkcall demux 4 GiB discard
alloc) was never actually filed in alkcall's consumer-findings-ledger —
only CF-001 is there. File it when next touching alkcall.

taskgraph: validate clean (42), no cycles
2026-08-30 06:03:29 +00:00
glm-5.3-flash 05d6bf8c2c fix(tasks): drop stray leading blank line breaking frontmatter parse (taskgraph 38/38) 2026-08-29 14:08:03 +00:00
glm-5.3-flash 5c16e68f75 chore(deps): prune unused deps, tighten tokio features, align tungstenite (HY-01, HY-05, HY-07, HY-08, HY-12)
- HY-01: openapiv3 -> dev-dependencies (test-only usage)
- HY-05: drop bytes (src sites renamed to axum::body::Bytes re-export),
  keep parking_lot (genuinely used); tokio "full" -> the seven features
  actually used (macros, rt-multi-thread, io-util, net, fs, time, sync)
- HY-08: test-support extends wss; dev tokio-tungstenite matches the
  wss feature set
- HY-12: tokio-tungstenite 0.28 -> 0.29 to match axum's tungstenite;
  duplicate roots in cargo tree -d: 9 -> 6 (tungstenite, cpufeatures,
  rand dupes collapsed)
- HY-07 ride-along: READ_SLOTS privatized
- CON-10 residue: verified already fixed (full_surface required-features)

Verified: cargo test (300), --all-features (371+36), --features mcp
(355+9), --features wss (316), check --no-default-features, clippy
(all-targets and --all-features, -D warnings), fmt --check
2026-08-29 14:06:36 +00:00
glm-5.3-flash a5b294e965 docs(adrs): reconcile WS-03 browser data-channel promise (ADR-067/048)
Record the v1 cut for browser-opened data channels over WS (review-001
WS-03): the design (ADR-067) stands; only the wiring is deferred.

- open-questions.md: add OQ-05 (deferred(scope: v1 cut)) with gap
  detail and deferred scope
- ADR-067: dated status amendment + v1-cut note at the data-channel
  step; References point to OQ-05
- ADR-048: dated reconciliation note — overlay bidirectionality is
  decided design, not a v1 implementation commitment
- websocket.md: status notes on §"Data channels for browsers" and
  upgrade step 7
- task review-001-ws-data-channel-decision: completed, Summary filled

Verification: taskgraph validate (38 tasks OK); cargo doc --no-deps
(pre-existing warnings only).
2026-08-29 13:57:24 +00:00
glm-5.3-flash 6b0e4db912 docs(tasks): review-001 ws-session-limits remediation complete 2026-08-29 13:51:23 +00:00
glm-5.3-flash 0e67c7c00f test(adapters): order-independent assert in MCP search filter test 2026-08-29 13:49:28 +00:00
glm-5.3-flash c93f7387ff docs(websocket): detached task lifetime semantics (WS-10) 2026-08-29 13:46:57 +00:00
glm-5.3-flash 25975ac2a8 fix(websocket): configurable WS read idle timeout (WS-01) 2026-08-29 13:45:54 +00:00
glm-5.3-flash fa73684ebe fix(websocket): configurable WS session cap (WS-09) 2026-08-29 13:37:08 +00:00
glm-5.3-flash 4747a12c02 fix(websocket): retain WsPumps handle on the server path (WS-08) 2026-08-29 13:31:33 +00:00
glm-5.3-flash 96560b0b78 fix(websocket): shutdown drops the held write sender (WS-07) 2026-08-29 13:13:19 +00:00
glm-5.3-flash 6fa2d4c036 fix(adapters): MCP tool-gateway fidelity (PRJ-07..10, PRJ-13)
- search honors the optional query substring filter (PRJ-07)
- search excludes both Sub andPub ops per ADR-041/ADR-068; dead match
  arms removed (PRJ-08)
- batch returns {"results": [...]} with {isError, output|error} items;
  tool description states the shape (PRJ-09)
- structuredContent is always an object: non-object outputs wrapped as
  {"result": <output>} (PRJ-10)
- argument errors are CallError values (retryable always present);
  non-string operation no longer reports 'missing required field'
  (PRJ-13)

Verified: cargo test --all-features, cargo test, clippy -D warnings,
fmt --check
2026-08-29 12:53:03 +00:00
glm-5.3-flash a9d17405a7 fix(adapters): input-schema enforcement + header/cookie params (OAI-02, OAI-03, OAI-07, OAI-09)
- build_request takes the op's input_schema and rejects undeclared
  input keys (INVALID_INPUT) before any outbound request is built;
  explicit `additionalProperties: true` opts into catch-all input;
  non-object inputs rejected (OAI-02)
- in: header parameters are stamped `wire: header` in the generated
  input schema and sent as upstream request headers, not query params;
  in: cookie fails import with a clear error (OAI-03)
- a spec parameter named `body` is rejected at import unconditionally
  (OAI-07)
- FromJsonSchema::new returns Result and validates method/path template/
  base_url at construction; registered visibility forced to Internal
  like from_openapi; module doc corrected (OAI-09)

Verified: cargo test, cargo test --all-features, clippy (both feature
sets, -D warnings), cargo fmt --check
2026-08-29 12:48:13 +00:00
glm-5.3-flash 7b83161171 docs(tasks): review-001 openapi-projection-fidelity remediation complete 2026-08-29 12:47:34 +00:00
glm-5.3-flash 4ef8499bbb fix(adapters): to_openapi runtime-truthful projection (PRJ-01..05, PRJ-11..15)
- /search, /schema: document the envelope wrapper and the real item/spec
  fields (PRJ-01/02); /search drops unreachable 401/403, documents 404
  (PRJ-15)
- error statuses: 422 for dispatch-path INVALID_INPUT /
  INVALID_OPERATION_TYPE; extractor 400s documented as the plain-text
  gap they are (PRJ-03); operation-declared errors projected by
  http_status with x-runtime-behavior: 500 on non-HTTP_* codes (PRJ-04
  project-honest decision) — no runtime changes
- /subscribe: 200+SSE only; event:error terminal contract documented
  (PRJ-05, GW-12)
-  components for requests/responses; CallRequest no longer inlined
  per-path (PRJ-14); all library expect() paths removed (PRJ-11)
- error projections folded into BTreeMaps: same registry =>
  byte-identical doc, sorted enums (PRJ-12)
- components.securitySchemes.bearerAuth + top-level security (PRJ-15)
- info.version 1.1.0 -> 1.2.0 (ADR-045 minor: additive documentation of
  the settled runtime contract)
- 31 unit tests incl. golden print-level assertions mirroring the routes
  tests' actual bodies and a determinism test

Verification: cargo test (288), clippy --all-targets -D warnings, fmt
--check, cargo doc --no-deps, cargo test --all-features (all green in a
clean worktree at HEAD; shared tree carries parallel agents' edits).
2026-08-29 12:47:10 +00:00
glm-5.3-flash 509850de3d docs(tasks): review-001 ws-pump-consolidation remediation complete 2026-08-29 12:12:16 +00:00
glm-5.3-flash e9ddf943e5 style(tests): cargo fmt for ws-upgrade-session ws-06 test 2026-08-29 12:11:57 +00:00
glm-5.3-flash 1db0ea88e5 refactor(websocket): one generic pump implementation (WS-11, COV-03) 2026-08-29 12:11:50 +00:00
glm-5.3-flash 92cc11a74f fix(websocket): byte-based caps for pending buffer + inbound WS sizes (WS-05, WS-06) 2026-08-29 12:00:04 +00:00
glm-5.3-flash 5024d99862 fix(websocket): validate chunk length on write side (WS-04, HY-09) 2026-08-29 11:25:51 +00:00
glm-5.3-flash 239f11323e fix(gateway): internal-op invisibility on /schema + cache headers (SRV-02, PRJ-06, GW-02)
- SRV-02: schema_handler applies the same is_internal_op -> 404 pre-check
  as /call, /batch, /subscribe, /publish (tested unauthenticated,
  anonymous-token, unauthorized-identity)
- PRJ-06: MCP schema tool runs the symmetric pre-check (NOT_FOUND for
  internal, FORBIDDEN for ACL-denied) before dispatch; enshrining test
  fixed
- GW-02: /search + /schema carry Cache-Control: no-store and
  Vary: Authorization on success and error responses

Verification: cargo test 270 passed; --all-features 337+9+6+8+10 passed;
clippy -D warnings clean (default + --all-features); fmt clean.
2026-08-29 11:13:57 +00:00
glm-5.3-flash 8700ed0fea fix(adapters): consumer adapter hygiene (CON-01, CON-03..CON-13)
- CON-01: from_mcp discovery follows tools/list pagination
  (rmcp list_all_tools); three-page paginating-server test
- CON-03: from_wss refuses ws:// with a Bearer token unless
  FromWss::allow_plaintext() is called explicitly (tests: refusal,
  opt-in, token-less passthrough)
- CON-04: audio variant of content_block_union_schema requires
  ["type","data","mimeType"]; jsonschema-validated audio block
- CON-05/07: import-time credential documented on both adapters;
  dead per-call capability read removed
- CON-06: 401 classification typed-first (downcast to rmcp
  StreamableHttpError<reqwest::Error>; AuthRequired/InsufficientScope/
  Client with status 401); a :40101 URL no longer misclassifies (tested)
- CON-11: transport tools/call failures declare MCP_TRANSPORT_ERROR;
  rmcp JSON-RPC errors preserve code (MCP_JRPC_<code>) and data
- CON-12: tool names validated at import (/, whitespace, empty →
  SchemaParse); unit + integration tests
- CON-13: tokens held as alkcall Secret<String> (zeroize, redacted Debug)
- CON-08/09: no close handles; explicit-limitation notes in from_mcp
  module docs, from_wss module docs, and ADR-070
- CON-10: full_surface [[test]] required-features = ["mcp","test-support"];
  cargo test --features mcp now compiles and passes

Verified: cargo test; cargo test --features mcp; cargo test --all-features;
cargo clippy (--all-features) --all-targets -- -D warnings; cargo fmt --check
2026-08-29 10:54:33 +00:00
glm-5.3-flash 314472012d fix(server): hyper knobs, decoy fidelity, cache + builder fixes (SRV-04..SRV-10)
- SRV-04: TokioTimer on h1+h2 builder, header_read_timeout 10s,
  h1 keep-alive on, h2 keep-alive 30s/10s; concurrency boundary documented
- SRV-05: with_decoy rebuild keeps extra routes (clone, not take)
- SRV-07: method_not_allowed_fallback serves the nginx-shaped 405
- SRV-08: UTF-8 percent-decoding, literal '+', tokio::fs syscalls
- SRV-09: /openapi.json cached at construction, generic 500 body,
  to_openapi returns Result (expect removed)
- SRV-10: ChannelsPolicy extension injection point on the WS upgrade;
  single token resolution via route ordering (WS layer before the
  router-wide auth route_layer)

Verification: cargo test 265 passed; --all-features server::/to_openapi::
green; clippy + fmt clean on touched files (remaining tree noise is a
parallel agent's in-flight from_mcp/from_wss/forward work)
2026-08-29 10:47:44 +00:00
glm-5.3-flash 1dc1d5af4f docs(tasks): review-001 response-decode fidelity (FWD-07/08/10/12) complete 2026-08-29 10:46:18 +00:00
glm-5.3-flash 7ac2dc5005 test(adapters): cover FWD-07/08/10 response-decode paths (vendor JSON, caps, loud auth errors, bounded error echo, non-SSE Sub stream) 2026-08-29 10:45:47 +00:00
glm-5.3-flash 9bb8487c6d fix(adapters): upstream response decode fidelity (FWD-07, FWD-08, FWD-10, FWD-12) — core, tests follow 2026-08-29 10:26:03 +00:00
glm-5.3-flash 5df91cda25 fix(adapters): resolve parameter/requestBody refs + reject import collisions (OAI-04, OAI-05)
- index components/parameters + requestBodies in OpenAPISpec; resolve
  bare $ref parameter and requestBody entries through the cycle-guarded
  resolver; unresolvable refs abort spec parse loudly
- reject path placeholders with no matching input-schema property at
  registration (no more silently percent-encoded literal placeholders)
- reject duplicate operationIds and path+method routes in one import
  batch instead of silent last-write-wins registration
- also reject a parameter named 'body' shadowed by requestBody (OAI-07
  adjacency, same code path)

Verified: cargo test (243), --all-features (322), clippy -D warnings
(default + all-features), fmt --check, doc --no-deps
2026-08-29 10:13:11 +00:00
glm-5.3-flash 9bc9e669e1 fix(gateway): SSE terminality, deadline, error-mapping fidelity (GW-03..GW-07, GW-12..GW-14)
- GW-04: /subscribe error events are terminal — scan-based emission of
  the error frame, then end of stream (matches call.error semantics).
- GW-05: enforce the 30 s gateway deadline via tokio::time::timeout in
  GatewayDispatch::invoke; hung handlers surface as TIMEOUT (504),
  streaming/sink stay unbounded per ADR-021.
- GW-07: gateway error paths route through the new identity-aware
  call_error_to_http_response_with_identity; retryable HTTP_429/HTTP_503
  now carry Retry-After on /call, /batch, /search, /schema, /publish.
- GW-13: SSE keep-alive (15 s comment frames) + retry: 15000 field.
- GW-14: module doc fixed (6 endpoints; /publish lives in routes.rs).
- GW-03/GW-12: mapping rides d7ee302's INVALID_OPERATION_TYPE mapper
  (documented in http-server.md table); 200-on-stream asymmetry
  documented.

Verification: cargo test (243 passed); cargo clippy --all-targets -- -D
warnings clean; cargo fmt --check clean.
2026-08-29 10:13:03 +00:00
glm-5.3-flash 713f1eba46 docs(tasks): review-001 forward-url-safety remediation complete 2026-08-29 10:09:33 +00:00
glm-5.3-flash 164a9d7543 fix(adapters): safe outbound URL construction (FWD-01, FWD-02)
- 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
2026-08-29 10:09:08 +00:00
glm-5.3-flash a4df859771 fix(server): cap /mcp body size (SRV-03)
Add tests for the /mcp body cap and complete the task file.

- oversized POST /mcp with declared Content-Length > 8 MiB -> 413
  before any body read
- oversized chunked POST /mcp -> 413 (counting-stream cut mid-body;
  rmcp maps body errors to 500, so the middleware sources the status)
- normal-size initialize round-trip unchanged
- task file: status completed, Summary filled

Verified: cargo test (219), cargo test --features mcp --lib (257),
cargo test --all-features (269 + integration), clippy default and
--all-features (-D warnings), cargo fmt --check.
2026-08-29 09:42:42 +00:00
glm-5.3-flash e38eaf1cea docs(tasks): review-001 ws-eof-signal remediation complete 2026-08-29 09:36:56 +00:00
glm-5.3-flash a9ac6f6cbd fix(websocket): lossless EOF signal + pending sweep (WS-02, CON-02)
- Replace the axum/tungstenite pump paths' Notify-based read-EOF signal
  with a retained tokio watch channel: a late subscriber (monitor
  spawned after session setup, or pump EOF before the receiver is
  taken) still observes EOF (WS-02).
- from_wss drop monitor: on EOF (or session close) fail all pendings
  retryable, then keep sweeping the pending map every 1 s — calls
  registered after the initial fail_all (the forgotten-session import
  path) resolve instead of hanging (CON-02).
- Tests: drop-during-registration race variants (forget + held
  session) and a post-EOF registration resolved via the sweep; the
  existing no-hang test stays green.

cargo test (219), cargo test --features wss (231, 3x for flake check),
cargo clippy --all-targets -- -D warnings, cargo fmt --check
2026-08-29 09:36:34 +00:00
glm-5.3-flash 5ff88756eb fix(websocket): lossless EOF signal + pending sweep (WS-02, CON-02)
Replace the axum/tungstenite pump paths' Notify-based read-EOF signal
with a retained tokio watch channel so a late subscriber observes EOF
regardless of when it fired. Extend the from_wss drop monitor to sweep
the pending map (1 s interval) once EOF is observed, so calls
registered after the initial fail_all also resolve retryable instead
of hanging.

cargo test; cargo clippy --all-targets -- -D warnings (default +
all-features); cargo fmt --check
2026-08-29 08:48:10 +00:00
glm-5.3-flash a943d142c4 fix(server): cap /mcp body size (SRV-03)
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.
2026-08-29 08:47:50 +00:00
glm-5.3-flash cc34c08e4e fix(adapters): incremental byte-level SSE parser (FWD-06)
Replace per-chunk parse_sse_frames with SseParser holding raw bytes
across chunks: reassembles frames split at TCP boundaries (the review's
silently-losing case), decodes UTF-8 per complete line so multi-byte
chars split across chunks survive, caps the buffer at 1 MiB
(SSE_EVENT_BUFFER_CAP) and dispatches a pending event at EOF.

forward_stream threads the parser through its unfold state and emits a
terminal error envelope on cap overflow. Existing single-chunk SSE test
assertions preserved; added multi-chunk, split-UTF-8, EOF-dispatch, and
cap tests.

Verified: cargo test (219 pass), clippy -D warnings, fmt --check.
2026-08-29 08:35:33 +00:00
glm-5.3-flash e4284a0d3c fix(server): auth-cover extra_routes + reserved-path rule (SRV-01, SRV-06)
- apply bearer_auth_middleware route_layer AFTER the extra_routes merge,
  so assembly-layer custom routes resolve the bearer token by default
  (ADR-046 §4); per-route opt-out via the route's own layer remains
- enforce RESERVED_PATHS per-method at build time: a probe MethodRouter
  occupied on all methods is pre-merged against extras, so a custom
  POST /search panics like a same-method overlap (ADR-046 §3)
- tests: auth resolves through an extra route; an extra route with its
  own layer opts out; reserved-path merge panics; non-reserved
  different-method merge stays legal; MCP bearer-gate test stays green
- ADR-046 §3: one sentence restating the per-method rejection rule

Verification: cargo test (215) ok, cargo test --all-features (260 +
integration) ok, clippy -D warnings (default + all-features) ok,
cargo fmt --check ok.
2026-08-29 08:28:15 +00:00
glm-5.3-flash d7ee302046 fix(gateway): publish validation + streaming + batch semantics (GW-01, GW-06, GW-08..GW-11, HY-13)
- 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.
2026-08-29 08:25:11 +00:00
glm-5.3-flash 42a2fa0ee3 docs(tasks): review-001 client timeout/retry remediation complete 2026-08-29 08:24:11 +00:00
glm-5.3-flash 4a557a0453 fix(client): drop unused import/ctor, needless ? (clippy -D warnings) 2026-08-29 08:23:56 +00:00
glm-5.3-flash b1529dd195 style(client): cargo fmt 2026-08-29 08:22:10 +00:00
glm-5.3-flash 015b2417b9 fix(client): redirect/retry policy hardening + timeouts (FWD-03..05, 09, 11)
- same-host redirect policy (scheme+host+port), cross-host redirects
  surface the 302 untouched - API-key/default headers cannot cross hosts
- retries gated to idempotent methods only (GET/HEAD/PUT/DELETE/OPTIONS);
  POST/PATCH/CONNECT/TRACE bypass the retry middleware entirely
- retry backoff jittered (Bounded) with tightened bounds [100ms, 2s] and
  a wall-clock budget (TotalRetryBudget, default 10s) on top of the count
- default request 30s / connect 10s / read 30s timeouts (gateway 30s
  deadline anchor); Retry-After ceiling 300s, configurable
- Retry-After recorded against the effective (post-redirect) URL;
  eviction prefers expired entries, then the farthest-future deadline;
  wake jittered (25% of remaining, capped 2s) to break the thundering herd
- reload() is async (tokio::fs); new() documented as one-shot blocking

verification: cargo test --lib client:: 36 passed; clippy/fmt applied
2026-08-29 08:21:42 +00:00
glm-5.3-flash 0a8d4d731f fix(adapters): bounded, cycle-safe $ref resolution (OAI-01, OAI-08)
resolve_refs_recursive recursed with no cycle detection and no depth
budget; a self-referential OpenAPI component stack-overflowed and
aborted the process (uncatchable, kills import()).

- add branch-scoped visited set on the JSON-pointer ref path: a ref
  re-entering its own expansion chain errors cleanly with
  AdapterError::SchemaParse naming the offending ref (OAI-01)
- add depth budget (MAX_REF_RESOLUTION_DEPTH = 64) bounding $ref hop
  chains and schema nesting height; over-deep specs error cleanly
  instead of exhausting the stack (OAI-01)
- clean loud error over depth-limited expansion: recursive schemas
  (trees, linked lists, cursor pagination) fail import rather than
  expand unboundedly
- shared refs to a common schema (diamond/repeated) still resolve —
  visited set is branch-scoped, not global
- OAI-08: replace the two guarded expects in from_value
  ("paths is object", "schemas is object") with if-let paths

Verification: cargo test 188 passed / 0 failed; clippy
--all-targets -D warnings clean; fmt --check clean
2026-08-29 07:53:01 +00:00
glm-5.3-flash 12b35e2c5f docs(tasks): decompose review 001 remediation Units 1-5 into taskgraph tasks
21 review-001 tasks across server/adapters/client/gateway/websocket/infra,
chunked from the 7-unit remediation plan in
docs/reviews/001-initial-implementation-review.md.

- Scope split by mechanism, not one-per-finding: 15 tasks in generation 1
  (parallelizable), 6 sequenced after their file-sharing precursors
- Deliberately deferred until dependent fixes land: projection/doc
  fidelity partial (Unit 6 beyond dependency hygiene), coverage backfills
  (COV-01..07 via in-task acceptance for forward.rs), and per-finding
  minors (OAI-06/07, HY-02/04/06/10/11, CON-08)
- Cross-crate WS-12 (alkcall demux 4 GiB discard alloc) noted for filing
  in alkcall, not here

taskgraph: validate clean, no cycles, 6 generations
2026-08-29 07:10:15 +00:00
glm-5.3-flash 54f8e2310e docs(review 001): initial implementation review — findings, coverage, remediation plan
Consolidated review of the 17-task initial implementation (tree 4a825d3):
8 subsystem passes + cargo-llvm-cov coverage analysis. Baseline: 256
tests green, clippy/fmt/doc clean, 93.86% line coverage.

Findings: 1 borderline-critical ($ref recursion aborts the process),
~30 major (extra_routes mounted without auth middleware, /schema leaks
Internal ops, /mcp unbounded body, forwarding URL construction/SSRF,
redirect credential leakage, non-idempotent retries, no default
timeouts, SSE chunk-boundary event loss, MCP schema ACL skip, from_wss
lost-EOF hang, projection-vs-runtime fidelity), and ~45 minor. Includes
verified-solid list, coverage gap analysis, and a 7-unit remediation
plan.
2026-08-28 17:22:46 +00:00
glm-5.3-flash 4a825d33e7 feat(infra): full-surface integration suite + docs sync + publish prep
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.
2026-08-28 16:07:56 +00:00
glm-5.3-flash bc99ec7188 test(websocket): connection-local overlay verification for browser-registered ops
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.
2026-08-28 15:49:25 +00:00
glm-5.3-flash 3a906cbd6a feat(adapters): from_wss consumer adapter behind the wss feature (ADR-070)
- FromWss: dial wss:// -> split_tungstenite_to_bytes (client-side twin
  of the axum WS byte-adapter; one seam, both directions, OQ-01) ->
  Connection::from_bidi(b"alk/channels") -> alkcall ChannelClient
  (channel 0 install + dispatch loop) -> alkcall from_call importer.
  No protocol fork: specs mirror the remote, provenance FromCall.
- Drop semantics (OQ-03 v1): session drop -> monitor fails all
  in-flight pendings retryable CONNECTION_CLOSED (WsPumps::read_eof
  Notify); no 30s-deadline hang.
- Bearer token via constructor/assembly layer (ADR-014 no-env-vars).

Production fix in the WS server half (upgrade.rs): the upgrade
identity now propagates to channel 0's CallConnection (was
AuthContext::anonymous -> dispatcher saw no identity, ACL checks ran
unauthenticated; services/list filtered scoped ops for all callers).

9 in-module tests incl. full round-trip consumer<->server (both halves
of the adapter together), ACL end-to-end, drop-no-hang.

Verified: cargo test (227 lib default), --all-features (227 lib + 5
MCP + 10 WS integration), clippy -D warnings (both), fmt.
2026-08-28 14:54:09 +00:00
glm-5.3-flash 4ac337c3a5 feat(adapters): from_mcp + to_mcp behind the mcp feature (rmcp 1.8)
from_mcp (src/adapters/from_mcp/):
- tools/list discovery over streamable HTTP; per-tool
  HandlerRegistration (Mutation, Once, FromMCP leaf, Internal;
  ADR-015/022)
- structuredContent-preferred output, ContentBlock-union fallback,
  isError -> MCP_TOOL_ERROR with content blocks as details (ADR-023)
- bearer token flows via capabilities key 'mcp' (ADR-014 no-env-vars)
- 19 unit tests + tests/from_mcp_integration.rs (5 tests vs a real
  rmcp streamable-HTTP MCP server)

to_mcp (src/adapters/to_mcp.rs):
- 4 fixed gateway tools (search/schema/call/batch, ADR-041); Sub ops
  excluded from search and uncallable (MCP is request/response)
- identity survives rmcp framing: bearer_auth_middleware stashes
  Option<Identity> in http::request::Parts extensions, call_tool reads
  it back from RequestContext extensions
- StreamableHttpService nested at /mcp in HttpAdapter's router,
  bearer middleware around it (feature-gated)

Streamable HTTP only (ADR-037): rmcp default-features off, no stdio.
Default build compiles without rmcp (cargo tree: 0 hits).

Verified: cargo test (182 lib default / 218 all-features) + 5 MCP
integration + 10 WS, clippy -D warnings (both), fmt.
2026-08-28 14:14:09 +00:00
glm-5.3-flash 7be91987ca feat(adapters): from_openapi adapter (parse + forwarding handlers)
Ported FromOpenAPI on the pre-staged foundations:
- openapi_spec.rs (from_json/from_yaml/from_str JSON-first per ADR-051,
  $ref resolution) — already shared with to_openapi
- forward.rs shared forwarding core (build_request/forward/
  forward_stream/parse_sse_frames) — already shared with from_jsonschema

New in this port:
- FromOpenAPI adapter: op-id normalization (declared or
  {method}_{path}), op-type detection (GET->Query, else Mutation;
  200/201 text/event-stream -> Sub), input schema from parameters +
  requestBody 'body', error schemas as HTTP_<status> (ADR-023),
  Internal visibility + FromOpenAPI provenance (ADR-015/022),
  Query/Mutation -> Once, Sub -> Stream (Pub never produced, v1)
- 47 in-module tests: wire-level integration over real TCP
  (echo + capturing servers), bearer/api-key/basic credential
  injection from Capabilities (ADR-014 no-env-vars), SSE streaming,
  YAML + from_str + ADR-051 yes-string guards
- removed dead_code allows from openapi_spec.rs (now consumed)

Verified: cargo test (182 lib), test --all-features (182+10 WS),
clippy -D warnings (both), fmt.
2026-08-28 14:04:48 +00:00
glm-5.3-flash 42239a0af5 feat(gateway,adapters): /publish endpoint (ADR-068) + to_openapi 6-endpoint projection
gateway-publish:
- GatewayDispatch::invoke_sink (internal:false, forwarded_for:None)
- POST /publish: NDJSON body, first line {operation, chunk} (OQ-02
  resolved: first-line convention; terminal errors = plain HTTP status
  + JSON body, not NDJSON lines); 404 internal/unknown, 401/403 ACL,
  400 INVALID_OPERATION_TYPE for non-Pub
- ADR-068 + open-questions.md updated with the OQ-02 resolution

adapter-to-openapi:
- src/adapters/openapi_spec.rs: OpenAPISpec model (JSON/YAML/from_str
  JSON-first per ADR-051, $ref resolution) shared by from/to_openapi
- src/adapters/to_openapi.rs: 6-endpoint projection, info.version
  1.0.0 -> 1.1.0 (minor: /publish addition per ADR-045), /publish
  NDJSON doc with 400 oneOf (INVALID_INPUT + INVALID_OPERATION_TYPE),
  ADR-023 error fidelity (protocol statuses, HTTP_<status> passthrough,
  internal-op exclusion)
- GET /openapi.json wired into HttpAdapter's router (bearer-auth layer)

Verified: cargo test (136 lib), test --all-features (136+10 WS),
clippy -D warnings (both), fmt. Doc validates against openapiv3.
2026-08-28 13:54:49 +00:00
glm-5.3-flash ad975408e7 feat(adapters): from_jsonschema single-endpoint adapter + shared forwarding core
- src/adapters/forward.rs: shared HTTP forwarding core (extracted from
  old from_openapi) — HttpServiceConfig/HttpAuthScheme, build_request
  with capabilities-based credential injection (no env vars), forward
  + forward_stream (SSE projection), parse_sse_frames
- src/adapters/from_jsonschema.rs: FromJsonSchema OperationAdapter
  (ADR-066) — one registration per call, FromJsonSchema provenance
  (leaf, Internal default), Sub -> HandlerKind::Stream (text/event-stream)
- adapted to alkcall 0.1.1: OperationType::Sub, alkcall::client
  adapter traits

Verified: cargo test (106 lib tests), clippy -D warnings, fmt.
2026-08-28 13:43:35 +00:00
glm-5.3-flash 4ba9b652b3 feat(websocket): WS upgrade route + channels session (server producer half)
- src/websocket/byte_adapter.rs: production WsByteStream from the POC —
  inbound bounded mpsc (64 slots, backpressure), outbound chunk parser
  emitting one WS message per chunk with 1 MiB split; write-side
  backpressure now uses futures mpsc poll_ready (POC spin-wait fixed);
  text messages closed with 1002; close mapping per websocket.md
- src/websocket/upgrade.rs: /alk/channels upgrade route — bearer auth
  (401 unresolvable), identity attached to the channels Connection,
  ChannelsAdapter + install_channel_zero running
  Dispatcher::run_loop_single_stream
- test_support module (feature test-support): WsClient, chunk/frame
  assemblers; shared with from_wss consumer path (ADR-070)
- tests/ws_upgrade_session.rs: 10 integration tests — call round-trip,
  services/list ACL-filtered, 3 MiB split, interleaved calls, ACL 403,
  internal-op NOT_FOUND, text->1002 close, disconnect mid-call no-hang

Verified: cargo test (95), cargo test --all-features (95+10),
clippy -D warnings (default + all-features), fmt.
2026-08-28 08:47:13 +00:00
glm-5.3-flash 0c1de05f85 feat(client): shared reqwest client host with retry stack and Retry-After
- src/client/http_client.rs: SharedHttpClient (ArcSwap rebuild-and-swap
  hot-reload), HttpClientConfig/ClientCertConfig, HttpClientBuildError
- src/client/retry_after.rs: inlined RetryAfterMiddleware — 429/503
  Retry-After (seconds + HTTP-date), bounded URL->deadline storage with
  earliest-deadline eviction, sleep-before-next-request
- middleware stack: RetryTransientMiddleware (exponential backoff) +
  RetryAfterMiddleware; credentials stay per-request via
  OperationContext.capabilities (no env reads)
- applied poisoned-lock recovery convention (into_inner)

Verified: cargo test (95 lib tests), clippy -D warnings, fmt.
2026-08-28 08:33:26 +00:00
glm-5.3-flash ea5ac83b57 feat(gateway): the 5 core gateway routes wired into the router
- src/gateway/routes.rs: /search /schema /call /batch /subscribe
- SSE projection: data frames per event, error event terminates,
  internal/unknown ops -> NOT_FOUND, query-op -> INVALID_OPERATION_TYPE
- /search + /schema ACL-filtered via services/list + services/schema
  discovery handlers; /batch ordered per-item envelope JSON
- gateway_router() merged into HttpAdapter's router under the shared
  bearer-auth route layer; decoy remains the fallback
- adapted to alkcall 0.1.1: OperationType::Sub, envelope error by value

Verified: cargo test (71 lib tests), clippy -D warnings, fmt.
2026-08-28 08:31:43 +00:00
glm-5.3-flash d070e548ad feat: server foundation (phase 1 core) — state, auth, healthz/decoy, gateway dispatch, HttpAdapter
Tasks completed: server-core-types, server-auth, server-healthz-decoy,
gateway-dispatch, server-adapter (5 of 17).

- src/server/state.rs: DecoyConfig + RouterState (alkcall type paths,
  6-endpoint reserved-path docs)
- src/server/auth.rs: bearer middleware + ResolvedIdentity extractor
  (10 tests: missing/malformed/basic/failed-resolution matrix)
- src/server/healthz.rs + decoy.rs: raw healthz; nginx-style 404,
  static site (path-traversal guarded), redirect decoys
- src/gateway/dispatch.rs: GatewayDispatch invoke/invoke_streaming
  (internal:false, forwarded_for:None, bounded deadline) +
  src/gateway/error.rs: CallError→HTTP status mapping (HTTP_<status>
  passthrough, retryable→Retry-After)
- src/server/adapter.rs: HttpAdapter ProtocolHandler — accept_bi →
  BiStream → TokioIo → hyper auto builder (h2 CONNECT enabled);
  integration tests over DuplexStream (request/response cycle, healthz,
  decoy 404)

Verified: cargo test (46 lib tests), clippy -D warnings, fmt,
test --all-features.
2026-08-28 07:35:02 +00:00
glm-5.3-flash a85500d3d9 docs: ws-byte-adapter POC complete (GO) — resolve OQ-01, update framing facts
POC at /workspace/ws-byte-adapter-poc/ (not on main), all tests green:
- call round-trip over axum WS ↔ adapter ↔ ChannelsAdapter ↔ channel-0
  Dispatcher (published alkcall API only, no forks)
- 3 MiB payload splits across 1 MiB WS messages, byte-intact reassembly
- 20 interleaved calls reassemble without corruption/cross-correlation

Findings merged:
- OQ-01 resolved: byte-stream both directions, bounded mpsc (64 slots)
  inbound, outbound chunk-header parsing (frame-as-two-chunks
  live-confirmed), 1 MiB message cap with split, flush no-op, close →
  EOF → REQ-CH-02
- websocket.md: chunk ≠ frame on channel 0 (frame reassembly required);
  operationId is the request payload key
- task ws-byte-adapter → completed with full Summary; ws-upgrade-session
  unblocks
2026-08-28 07:14:32 +00:00
glm-5.3-flash 63dc4b6d06 docs: implementation plan (TTY precedents folded in); task decomposition (17 tasks)
Plan updated with the alknet-tty findings: the drainer pattern
(single ordered writer) makes outbound chunk-boundary parsing sound;
TestStdinSink's try_send→Full→Pending is the inbound backpressure
precedent; OQ-01(a) now cites the reference.

Task graph (taskgraph-validated, 17 tasks, 6 generations, no cycles):
- tasks/server/: core-types, auth, healthz-decoy, adapter
- tasks/gateway/: dispatch, routes, publish
- tasks/websocket/: byte-adapter (research POC), upgrade-session, overlay-ops
- tasks/adapters/: from-openapi, from-jsonschema, to-openapi, from-wss, mcp
- tasks/client/: http-host
- tasks/infra/: integration-suite (phase 4)

Critical path runs through server core → adapter → WS session →
overlay tests → integration suite. High-risk tasks are the three WS
tasks, de-risked by the ws-byte-adapter POC blocking upgrade-session.
2026-08-28 06:05:45 +00:00
glm-5.3-flash eaf1a203bc docs: correct WS framing claims from spike; add implementation plan
Spike against alkcall source resolved ADR-067 assumptions:
- write_chunk issues header+payload as separate write_alls; channel
  0's write_frame issues prefix+body separately — a logical write can
  surface as multiple chunks, so the WS adapter must parse outgoing
  chunk boundaries (byte-stream treatment both directions), not assume
  write-per-chunk or message-per-chunk
- MAX_CHUNK_LEN is 16 MiB; the WS path needs a practical message cap
  with oversized chunks split across messages
- install_channel_zero + run_loop_single_stream confirmed as the exact
  server-side seam; EOF/teardown invariants already specified by
  alkcall (REQ-CH-01/02)

Corrections applied to websocket.md, ADR-067, OQ-01.

docs/plans/implementation.md: scoped plan guiding task decomposition —
spike findings, 4-phase build order, OQ dispositions, task conventions.
2026-08-28 05:55:03 +00:00
glm-5.3-flash 320ea87b08 docs: port architecture specs and ADRs from alknet-http; write new alkhttp ADRs 067-070
Phase 1 (SDD) — architecture documentation:

Ported specs (adapted for alkcall, producer/consumer terms, 6-endpoint
gateway, channels-over-WS, Sub/Pub operation types):
- overview.md, http-server.md, http-adapters.md, http-mcp.md
- README.md index (rewritten for alkhttp)

New ADRs:
- 067: WebSocket carries the channels protocol (8-byte chunk demux,
  channel 0 = alk/call, upgrade path /alk/channels)
- 068: gateway /publish endpoint for Pub operations (NDJSON body)
- 069: WebTransport out of scope in alkhttp (alknet concern)
- 070: from_wss consumer adapter (wss feature, tokio-tungstenite)

Ported ADRs (25, same numbers, port notes + amendments where the
extraction changed facts): 001-004, 010, 014, 015, 017, 022, 023, 027,
034, 036, 037, 039, 041, 042, 044, 045, 046, 047, 048, 049, 051, 066.

websocket.md rewritten for the channels session; open-questions.md
seeded (OQ-01 WS byte-stream adapter, OQ-02 /publish framing,
OQ-03 from_wss reconnect, OQ-04 browser client ownership).

Verified: cargo test, clippy -D warnings, fmt, doc --no-deps.
2026-08-27 14:19:24 +00:00
glm-5.3-flash 28c521b2f3 feat: scaffold crate with alkcall 0.1.1 dependency
Empty module tree (adapters, client, gateway, server, websocket) matching
the AGENTS.md subsystem map. Features: h2/http1 (default), mcp (rmcp),
wss (tokio-tungstenite, for the from_wss consumer adapter).

Verified: cargo check (default), cargo check --all-features.
2026-08-27 12:50:43 +00:00