33 Commits
Author SHA1 Message Date
glm-5.3-flash 449661eb87 chore: release alkhttp 0.7.0
- version bump 0.6.0 -> 0.7.0 (minor per the dep-wave convention:
  0.5.0 rode alkcall 0.8.0; see the preceding consume commit)
- README usage snippet 0.5.0 -> 0.7.0
- changelog: cut [0.7.0] with the alkcall 0.9.0 consumption under
  Changed (the stub-sweep audit: no ManagerError/RelayError matching,
  no Establishment construction, no marked-pub surface reached through
  the HTTP API) and the two ride-through fixes under Fixed
  (register_imported Result in the WS overlay tests, fuzz/shared spec
  alignment)

Verification: cargo test/clippy/fmt/doc green in the preceding deps
commit; no source change in this commit
2026-10-14 05:20:13 +00:00
glm-5.3-flash c89aa65fb2 chore(deps): consume alkcall 0.9.0
- bump alkcall 0.8.1 -> 0.9 (gateway feature unchanged). No code change
  forced: none of the 0.9.0 breaking surfaces are constructed or
  pattern-matched in this crate — no ManagerError match arms (the new
  InvalidAdopt variant changes nothing here), 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, per the 0.8.0
  audit), and the op/register forward-through refactor does not touch
  the from_wss import filter or the adapter-registered leaf bundles
- ride-through fixes: tests/ws_overlay_ops.rs now expects
  register_imported's new Result<(), String> return (8 sites assert
  registration success instead of discarding the value — the bool
  return they consumed was ignored anyway); fuzz/shared follows the
  main crate to alkcall 0.9 so the harness replay resolves one
  alkcall version (the stale 0.8.1 spec pinned two copies against
  alkhttp's requirement and broke the shared-crate build)
- 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

Verification: cargo test 441+70 pass (default), 520+70 pass
(all-features), clippy --all-features --all-targets -D warnings clean,
fmt --check clean, doc --no-deps clean, fuzz corpus replay 21/21
2026-10-14 05:19:29 +00:00
glm-5.3-flash 4b32f84bd2 chore: release alkhttp 0.6.0
The fuzzing adoption waves (commits 5971c0a..a16dee7) plus the alkcall
0.8.1 patch pickup, released as a minor bump:

- Added: fuzz/ infra (5 nightly targets, stable-toolchain corpus-replay
  gate), public SSE parse types (SseParser/SseEvent/SseParseError/
  SSE_EVENT_BUFFER_CAP), the WriteChunkWalk/Walk chunk-walk API, and
  the fuzzing re-export hubs.
- Fixed: FWD-20 (SSE dribble drain quadratic -> linear), FWD-21
  (WriteChunkWalk failure arms carry the pre-failure pieces), FWD-22
  (harness re-frame guard-CR; no crate change).
- Changed: alkcall 0.8.1 (duplicate adopt/open collision fix).
- Doc: fixed broken intra-doc link surfaced by SSE_EVENT_BUFFER_CAP
  going public.

Verified: cargo test (457 passed), cargo test --all-features (590),
cargo clippy --all-targets -- -D warnings, cargo fmt --check,
cargo doc --no-deps (0 warnings), fuzz corpus replay (21 passed),
cargo publish --dry-run --allow-dirty.
2026-09-29 21:02:32 +00:00
glm-5.3-flash 5971c0a0d6 fuzz: adopt fuzzing (wave 1) + fix the SSE dribble quadratic (FWD-20)
Adopt the alk*/fuzzing posture (alkcall 0.8.1 precedent) — the dep
bump this ride-along builds on was 4005517:

- docs/plans/fuzzing.md: the four-target plan (sse_parser,
  ws_chunk_framing this session; spec_import + the stateful wave
  later), the infrastructure blueprint, and the corpus/campaign
  policies (§3's table tracks progress)
- fuzz/ workspace (the sibling layout): nightly-pinned subtree,
  stable fuzz/shared invariant library (corpus replay = the standing
  fuzz gate), detached runner (never a foreground child of an agent
  session), JSON dict, deterministic seed generator; 80 committed seeds
- two wave-1 targets: sse_parser (SseParser::feed + the FWD-17
  envelope mapping — the parser every subscription forwards through)
  and ws_chunk_framing (WriteChunkWalk, the write pump's chunk walk)
- crate-side surfacing: SseParser/SseEvent/sse_event_envelope are pub
  behind the adapters::forward::fuzzing re-export hub; the write
  pump's inline chunk loop extracted as WriteChunkWalk (pump byte
  behavior unchanged — 441 tests green); retained_bytes() diagnostic
  (the alktunnels/alksocks posture)
- root Cargo.toml gains the explicit [workspace] table with
  fuzz/ excluded (auto-discovery would pull the nightly-consumed
  dev-deps into the stable build — the alkcall trap); fuzz/ joins the
  publish exclude list
- AGENTS.md verification checklist gains the corpus-replay line

FWD-20 fix, found by driving the new sse_parser harness: feed()
rescanned the whole reassembly buffer per feed — a dribble-fed
subscription (one unterminated line over many small chunks) cost
quadratic CPU (1 MiB dribble ≈ minutes per connection, unbounded
total). Line assembly now walks only the arriving chunk: the buffer
holds just the current line, the scan never revisits drained bytes.
1 MiB dribble: ~5 min (quadratic) → 21 ms (linear). Regression test
sse_parser_dribble_feeds_do_not_rescan_the_buffer.

Verification: cargo test 441 passed; cargo test --all-features ok;
clippy --all-targets -- -D warnings (main + fuzz/shared) clean;
fmt --check (main, fuzz, fuzz/shared) clean; cargo fuzz build clean;
corpus replay (cargo test --manifest-path fuzz/shared/Cargo.toml) 80
seeds green.

Refs: alkcall docs/research/fuzzing.md (§7.9 posture), alksocks
08a3694 (the sibling wave-1 shape), docs/plans/fuzzing.md §2
2026-09-29 08:32:29 +00:00
glm-5.3-flash 40055170a0 build(deps): bump alkcall to 0.8.1
Picks up the duplicate adopt/open collision fix found by alkcall's
manager_routing fuzz campaign (alkcall CHANGELOG 0.8.1): a duplicate
adopt_channel/open_channel no longer replaces the live channel's
state. alkhttp reaches the fixed paths via the shared ChannelManager;
no alkcall API surface used by this crate changed.

Verified: cargo test (456 passed), cargo test --all-features,
clippy --all-targets -- -D warnings, fmt --check.
2026-09-29 06:42:17 +00:00
glm-5.3-flash a63f4ed2c9 chore(deps): consume alkcall 0.8.0
- 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
2026-09-18 13:48:23 +00:00
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
glm-5.3-flash 0b60b8d0be chore: release alkhttp 0.2.0
- version bump 0.1.0 -> 0.2.0 (new public API: OpenableAlpn
  establisher fields + with_establisher builder; rides alkcall
  0.5's semver-incompatible channels types)
- README usage snippet 0.1 -> 0.2
- changelog: cut [0.2.0], add the missing alkcall 0.5.0 wave
  (ADR-049 establisher pass) to the dependency history

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-06 20:10:12 +00:00
glm-5.3-flash 80d6ba0e5a feat(websocket): ride alkcall 0.5.0 — OpenableAlpn establisher + timeout (ADR-049 Unit 3)
Mechanical pass for the alkcall 0.5.0 bump (review 006 sequencing:
ADR-049 → alkcall 0.5.0 → alkhttp mechanical pass):

- bump alkcall 0.4 → 0.5 (gateway feature unchanged)
- OpenableAlpn gains establisher: Option<OpenEstablisher> and
  establisher_timeout: Option<Duration> (both default None via
  OpenableAlpn::new — existing constructions compile unchanged) plus
  a with_establisher(establisher, timeout) builder
- the install_channel_zero ferry calls
  register_openable_with_establisher, threading both fields through
- docs updated (websocket.md, adapter.rs doc comments)

The alkcall 0.5.0 open_channel error-type change (ADR-049 §4) needs
no change here — this crate never calls open_channel (from_wss uses
ChannelClient::from_connection only).

Verification: cargo test (454 passed), cargo test --all-features
(587 passed), cargo clippy --all-targets/-D warnings (default +
all-features), cargo fmt --check
2026-09-06 20:04:25 +00:00
glm-5.3-flash 5f12abf80e chore: drop dead Cargo.lock exclude entry
cargo always packages the lockfile for libraries (since 1.62), so
the exclude entry did nothing. Package contents unchanged.
2026-09-05 18:22:34 +00:00
glm-5.3-flash ce6c29a6c8 fix(features): client implies openapi, per the spec
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.
2026-09-05 18:04:56 +00:00
glm-5.3-flash 1ce886b9d4 chore: alkcall 0.3 -> 0.4.0 (registry input_schema enforcement)
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).
2026-09-05 06:34:25 +00:00
glm-5.3-flash 3dee46aead chore(deps): consume alkcall 0.3 — per-session fork, serving loop, op/register
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.
2026-09-04 14:55:19 +00:00
glm-5.3-flash 58665f2061 docs: add crate README, MIT/Apache license files
- 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
2026-09-01 11:18:36 +00:00
glm-5.3-flash a80f9948b8 feat(build): feature-sided builds — server/client sides independently selectable (ADR-039 Amendment 1)
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.
2026-08-31 17:19:05 +00:00
glm-5.3-flash 8e8e1f2b14 refactor(gateway): migrate to alkcall 0.2 promoted gateway module
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.
2026-08-31 10:36:32 +00:00
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 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 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 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 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 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 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 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 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 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 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