Commit Graph
209 Commits
Author SHA1 Message Date
glm-5.3-flash 0766f4bebe feat(server): door-surface Basic auth tolerance (review 008)
review 008 resolution:

- AH-1: door_auth_middleware on extras doors resolves
  Authorization: Basic base64(user:pass) — password field as the
  token (GitHub-PAT shape, git-lfs / git smart-HTTP clients) — through
  the same IdentityProvider::resolve_from_token backend as Bearer; no
  new trait method, resolve-fails -> None fallback preserved. Bearer
  surfaces stay Bearer-only: the gateway endpoints, /openapi.json,
  /healthz, the MCP nest, and the WS upgrade path never resolve Basic.
  The 'Bearer-only is the auth mechanism' doc line flips (ADR-073).
- AH-2 ride-along: extras door route tables are static — the merged
  router owns the decoy fallback, a second fallback panics at
  construction; documented on with_extra_routes and ADR-046 §1.

docs: ADR-073, ADR-046 §1/§4 amendment, ADR-004 presentation table,
review 008 marked resolved; new server::* re-exports; dep:base64
behind the server feature.

Verification: cargo test (449 pass, incl. door Basic resolve-through
and gateway-stays-Bearer-only pins), test --all-features (528),
clippy --all-targets -D warnings, fmt --check, fuzz corpus replay
(21/21), cargo doc.
2026-10-17 16:09:36 +00:00
glm-5.3-flash ad63507124 feat(server): thread alkcall 0.10 ownership wiring onto the HTTP surface
Ride the alkcall 0.10 gateway ownership seam (review 012, ADR-048
amendment) into the door layer:

- HttpAdapter::with_ownership_provider /
  HttpAdapter::with_static_ownership_fallback mirror alkcall's builder
  shape; OwnershipProvider re-exported next to GatewayDispatch
- RouterState carries the wiring; GatewayState::dispatch is the single
  spine builder for both the gateway routes and the MCP nest
- loud default passes through: a resource_type-gated op on an unwired
  spine is refused (FORBIDDEN envelope -> 403/401) on HTTP exactly as
  on the native wire
- WS native-session path untouched (consults ownership natively)

fix: with_ws_max_sessions never stored the fresh session-slot
semaphore; later builder calls silently reverted the cap. Builder
state now assembled through one router_state() helper.

infra: fuzz/shared follows to alkcall 0.10 (two alkcall copies in one
build would type-clash); alkhttp 0.8.0 per the dep-wave convention.

Verification: cargo test (444 pass, incl. 3 new call_resource_gated_*
HTTP-surface pins), clippy --all-targets -D warnings, fmt --check,
test --all-features (520), fuzz corpus replay (21/21), doc.
2026-10-17 16:00:12 +00:00
glm-5.3-flash 1cac63fdba docs(review): 008 — HTTP-door consumer evidence (LFS Basic auth, route-fallback constraint)
Report-only from alkgit's LFS POC: AH-1 the shared bearer middleware
is Bearer-only while real git-lfs authenticates Basic on the batch;
AH-2 extras doors cannot carry a second route fallback (docs-only
record). No mechanism change fixed here; dispositions session-owned.
2026-10-17 07:28:45 +00:00
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
v0.7.0
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 2cf0dc7bea docs + clippy: drop the retired C-08 stub reference; cloned_ref_to_slice_refs
- websocket/upgrade.rs: OpenableAlpn's spec doc advertised the removed
  `channel:pub_open_not_implemented` stub (upstream C-08, fixed in
  alkcall with the single-publish fixes) — rewritten to the current
  contract: Pub-typed marked specs are refused loudly at registration
  by `register_openable_with_establisher`; marked pub openables route
  through `ChannelCore::register_pub_openable`. Also dropped the
  stale 'alkcall 0.6.0' version pin
- adapters/from_openapi.rs: clippy rust-1.99
  `cloned_ref_to_slice_refs` — std::slice::from_ref instead of a
  single-element to_string slice

Verified: cargo test (458 ok), clippy --all-targets -D warnings,
fmt --check
2026-10-13 11:32:16 +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.
v0.6.0
2026-09-29 21:02:32 +00:00
glm-5.3-flash a16dee7385 docs(fuzzing): sse_parser 45-min post-FWD-22 rerun clean
Exited 0 at 2765 s: 96k execs at ~33/s, coverage 1378 edges / 6655
features / 734 corpus, still growing at budget end, zero findings.
Wave 4 is fully done: five of five targets exited 0.
2026-09-29 20:17:06 +00:00
glm-5.3-flash a7d3e3afc3 docs(fuzzing): wave-4 long-campaign results + FWD-22 recorded
45-min release-budget campaigns, all five targets launched
concurrently: ws_chunk_framing / spec_import / ws_session_opseq /
retry_throttle all exited 0 (coverage saturated or still growing at
budget end; details in plan §5). sse_parser aborted at 1913 s on
FWD-22 (harness-assert fix, previous commit); 45-min post-fix rerun
in flight. Corpus merges deliberately deferred.
2026-09-29 19:25:42 +00:00
glm-5.3-flash b78b9a2618 fix(fuzzing): FWD-22 — guard-CR re-frame makes the SSE round-trip total
The sse_parser re-frame probe emitted 'data: <line>' unguarded, so a
payload CR (interior CR in multi-line data: the payload line is '\r')
was consumed by strip_cr at re-parse time and the round-trip lost it.
Wave 1 had skipped only the terminal-CR case. Found ~32 min into the
first 45-min sse_parser campaign.

- frame_event emits 'data: <line>\r': the guard CR is the line
  terminator, strip_cr removes exactly it, the payload CR survives
- drop the terminal-CR skip; the round trip is now total over
  JSON-encodable payloads (JSON never encodes a raw CR, so the
  residual asymmetry is the serde_json non-preserved key-order class)
- no crate-side change: the parser was correct (data: x\r\r\n ->
  x\r); only the harness re-encode was weak
- regression: 2 new seeds (interior CR via \r escape; raw CR via CRLF
  framing, two-line doc) + unit cases

Verification: shared 21/21 (default + no-default-features), main
crate green, clippy -D warnings clean, fmt clean, cargo fuzz build
clean
2026-09-29 19:25:39 +00:00
glm-5.3-flash 4e8a2cfddd docs(fuzz): record wave-3 campaign results + FWD-21 2026-09-29 17:28:23 +00:00
glm-5.3-flash e023d3275e feat(fuzz): target 4 stateful wave — ws_session_opseq + retry_throttle
Two stateful op-sequence harnesses (fuzz/shared):

- ws_session_opseq: the WS byte adapter's generic pumps driven
  end-to-end over a mock socket flavor through the new
  byte_adapter::fuzzing drive hub (FuzzMockSocket flavor,
  FuzzChannels/FuzzWriteSide channel bundle, pump spawn funnels,
  FuzzInboundChunkProgress). Asserts lossless inbound forwarding
  (exact after the teardown joins), the WS-01 walk's completed-chunk
  count vs the declared frame count, the WS-15 close mapping
  (1002/1011/verbatim-requested + per-cause reasons), lossless write
  framing onto the declared chunk stream (FWD-21's failure-carry
  included), lane-failure isolation (the alkcall 0.8.1 class), and
  pump termination within the bound.
- retry_throttle: the inlined RetryAfterMiddleware's throttle map
  through the new client::fuzzing hub — capacity bound, the
  expired-first + Farthest-future eviction policy, the ceiling clamp,
  refresh contraction, the Retry-After parse partition, and the
  jitter bounds.

16 committed seeds (8 per target) in gen_fuzz_seeds.py, hand-encoded
against the arbitrary 1.4.x derive layout with ceiling-division
variant tags and per-element keep-going bytes, pinned by
seed-decode tests. fuzz/shared gains bytes/futures/tokio/url/
http/httpdate/arbitrary deps.

Verification: main crate 441 default tests, fuzz shared replay 21/21
(default + no-default-features), cargo fuzz build clean (5 targets),
clippy+fmt clean both crates.
2026-09-29 17:28:20 +00:00
glm-5.3-flash 0ae53d2d27 fix(websocket): WriteChunkWalk failure arms carry the parsed pieces
FWD-21, found minutes into the first ws_session_opseq campaign: one
feed that drains a complete chunk and then hits an oversize header
(or the pending cap) in the same call returned
Walk::Oversize/PendingOverCap and silently discarded the already
drained pieces — the walk's own consumption-accounting contract
('every parsed byte is either emitted or retained', wave-1
invariant 6) was violated by the crate. Production could not reach
the shape (the mux's per-write invariant caps pending at one chunk +
header), so impact was nil, but WriteChunkWalk is public API and the
wave-1 split_walk equality check was skipped on exactly this path.

- Walk::Oversize(Vec<Vec<u8>>) / Walk::PendingOverCap(Vec<Vec<u8>>)
  carry the pre-failure pieces (user-approved semver-relevant API
  change)
- run_write_pump emits the carried pieces before fail_write_pump, so
  a 1011 close never swallows a legal chunk the mux already counted
  as written
- the ws_chunk_framing harness's split-drive failure arm now
  reconciles the parsed-before-failure bytes across the whole and
  split drives; a regression seed covers the drain-then-fail shape

Verification: main crate 441 default / 520 all-features tests, fuzz
shared replay 21/21 (default + no-default-features), cargo fuzz build
clean, clippy+fmt clean both crates.
2026-09-29 17:28:14 +00:00
glm-5.3-flash 27478f936b docs(fuzz): wave-2 spec_import campaign clean — 2.34M execs, zero findings 2026-09-29 10:18:21 +00:00
glm-5.3-flash e6491e31c7 feat(fuzz): target 3 spec_import — import-surface fuzz harness + 42 seeds
- fuzz/shared/src/spec_import.rs: invariants over the import-parse
  surface — the three OpenAPISpec constructors (str/json/yaml,
  ADR-051 JSON-first), the YAML→JSON normalization boundary
  (reject-loudly partition: non-finite floats, pointer keys), the
  compile/harden/validate lane (hardening partition, validate
  determinism, closed-by-default unknown-key probe), the FromMCP
  build_spec tool-shape lane, and the $ref-bounded resolver lane
  (cycles/hop chains/deep nesting fail cleanly, no hang, no stack
  blowout).
- fuzz/fuzz_targets/spec_import.rs: thin fuzz_target! wrapper.
- 42 committed corpus seeds via gen_fuzz_seeds.py (valid JSON/YAML
  docs, structural failures, YAML normalization edges, $ref cycles/
  chains/unresolvable/external, schema-validation edges, MCP
  tool-shape edges); corpus-replay gate count floor 12.
- fuzzing exposure hubs next to the wave-1 one:
  openapi_spec::fuzzing, input_validation::fuzzing (opaque
  FuzzCompiledValidator newtype — the pub(crate) validator never
  leaks), from_mcp::fuzzing (mcp feature).
- fuzz/shared gains openapi/mcp features (default on); json.dict
  extended with the OpenAPI token set (75 unique tokens).
- clippy follow-up in wave-1's ws_chunk_framing replay test
  (unnecessary u32 casts against the newer lint).
- docs/plans/fuzzing.md §3/§6 target 3 → implemented; fuzz/README
  target table + campaign-advice lines updated.

Verification: corpus replay 11/11 green (default and
--no-default-features), cargo fuzz build clean, main crate 457
default / 590 all-features tests green, clippy+fmt clean both crates.
Campaign: detached 10-min smoke run — see docs/plans/fuzzing.md §5.
2026-09-29 10:06:03 +00:00
glm-5.3-flash 84c4b48407 fuzz: wave-1 smoke campaigns clean + grow-corpus gitignore fix
Both 10-minute detached campaigns (§5 budget) ran to completion:
sse_parser 18.9k execs / 1100 edges (still discovering at budget end),
ws_chunk_framing 4.8M execs / 245 edges (saturated) — zero crashes,
hangs, OOMs, or leaks on all fork jobs; artifact dirs empty.

One policy gap the first campaigns exposed: the grown corpus entries
(hash-named files in fuzz/corpus/<target>/) leaked as git noise under
the un-ignored corpus dirs. The hash-pattern gitignore now separates
the committed seed-* files from campaign output, per the quinn/h2
model.

docs/plans/fuzzing.md: §3 table marks targets 1-2 implemented; §5
gains the grow-corpus policy + campaign results; §6 sequencing marks
step 1 done. FWD-20 already carried the fix log from 5971c0a.

Verification: corpus replay 80/80 green, cargo test 441 passed, fmt
--check clean.
2026-09-29 09:18:08 +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 779e3ea908 docs(plans): fuzzing plan for alkhttp (4 targets, sibling pattern)
Adopts the fuzzing pattern proven in alkcall/alktty/alktunnels/
alksocks: fuzz/ workspace with stable-toolchain shared invariant
crate, committed seed corpora, corpus replay as the standing gate,
detached runner for campaigns. Four targets planned — sse_parser and
ws_chunk_framing (this session), spec_import and the stateful wave
(later sessions). §3 table and §6 sequencing track progress.
2026-09-29 07:22:15 +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 911f186629 chore: release alkhttp 0.5.0
- version bump 0.4.1 -> 0.5.0 (minor per the dep-wave convention:
  0.3.0 rode alkcall 0.6.0, 0.4.0 rode alkcall 0.7.0)
- README usage snippet 0.4.1 -> 0.5.0
- changelog: cut [0.5.0] with the alkcall 0.8.0 consumption under
  Changed — the additive-only audit (reply fields, relay/hub-leg,
  flavor-form discovery) and the one ride-through discovery change
  (explicit channel_open_alpn for non-standard open-op names)

Verification: cargo test/clippy/fmt/doc green in the preceding deps
commit; no source change in this commit
v0.5.0
2026-09-18 13:48:26 +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)
v0.4.1
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
v0.4.0
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
v0.3.0
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
v0.2.0
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.
v0.1.0
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 d08ea44ad1 docs(changelog): record the alkcall 0.3 -> 0.4.1 consumption waves
The [Unreleased] section still led with the alkcall 0.2 bump; the
0.3 (per-session fork, op/register, UP-03), 0.4.0 (registry
input_schema enforcement), and 0.4.1 (early-arrival chunk parking)
waves were unrecorded. Also removes a copy-paste duplication in the
CF-003 entry.

Verification: cargo test, clippy (both feature sets), fmt, doc,
publish --dry-run — all green.
2026-09-05 18:03:03 +00:00
glm-5.3-flash a131325d28 chore: alkcall 0.4.0 -> 0.4.1 (early-arrival park fix) 2026-09-05 07:05:28 +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 2e15204aca fix(docs): resolve the 5 pre-existing rustdoc warnings
cargo doc --no-deps was not actually clean before review 007's
remediation — it emitted 5 warnings that went uncounted (grep for
"^error|^warning" in the gate runs matched only on error/warning at
line start, and the review baselines recorded "clean" without a
counting check; the warnings were first noticed while re-verifying
the review-007 gate set). All pre-existing, none introduced by
review 007:

- src/adapters/mod.rs: the bare [`OpenAPISpec`] intra-doc link did
  not resolve (the re-export sits in the same module, but rustdoc
  resolves module-level links against the module's own scope) —
  spelled out as `openapi_spec::OpenAPISpec`
- src/websocket/mod.rs: [`upgrade`] did not resolve from the
  `websocket` module doc (the submodule is not in scope for the
  parent's doc links) — plain `upgrade`
- src/websocket/upgrade.rs:215: [`CallConnection`] had no import in
  scope — spelled out via the full alkcall path
- src/websocket/upgrade.rs:291: [`install_channel_zero`] linked a
  private item from public docs — plain `install_channel_zero` hook
- src/server/adapter.rs:274: [`crate::websocket::OpenHandler`] is
  not re-exported from `websocket` — spelled out via the alkcall
  path

Verification: cargo doc --no-deps 0 warnings (was 5); cargo test 454
passed / 0 failed; cargo test --all-features 587 passed / 0 failed;
clippy (both configs) clean; fmt clean.

Review: docs/reviews/007-ws-data-channel-surface-review.md (the
baseline's "cargo doc → clean" claim was wrong on this dimension)
2026-09-05 05:59:54 +00:00
glm-5.3-flash 802d94ec07 docs(review 007 Unit 2): WS-31 discovery-shadowing note + record corrections
- WS-31: websocket.md §"Data channels for browsers" + ADR-067's landed
  note record that WS-session discovery is the bootstrap set — the
  hook's bootstrap `services/*` registrations overwrite a
  base-registry `services/*` registration on the WS path by design
  (a deployment's custom `services/list` is shadowed on WS sessions
  only).
- ADR-048's landed note: correction + completion — the WS-26
  retention sentence was aspirational at the landed commit (WS-28) and
  is now real; the UP-02 posture's override half is now an explicit
  surface (`with_ws_op_register_acl` / `OpRegisterAcl`), with the
  note that `ChannelsPolicy` could not carry an op ACL.
- ADR-067's landed note: review-007 notes (WS-28 fix + gate, WS-29
  surface, WS-31 record).
- OQ-05 resolution: the retention claim carries the WS-28 correction.
- review-006 UP-02 log + WS-26 paragraph: corrections marking what the
  pre-fix tree did not have, with the landed remediation named.
- review-002 WS-17: the "bounded at 64 sessions" claim corrected —
  the bare-registry semaphore was per-request and bounded nothing;
  `SessionSlots` is the shared-cap surface.
- review-007 status: open for remediation → remediated, with the
  decisions taken (both "implement" options) and the gate names.

Verification: cargo test 454 passed / 0 failed; cargo doc --no-deps
clean (6 pre-existing warnings, identical at baseline).

Review: docs/reviews/007-ws-data-channel-surface-review.md
2026-09-05 05:45:31 +00:00
glm-5.3-flash 24c2e9a224 feat(websocket): WS-29/30/32 — op/register ACL surface, SessionSlots, builder-path gate
Review 007 Unit 2 (the two "implement" decisions taken during
remediation, plus the coverage gap):

- WS-29: the `op/register` override surface review-006 UP-02 and
  ADR-048 recorded as landed is now implemented. The hook threads an
  `op_register_acl` `AccessControl` into `op_register_spec` (the
  permissive `AccessControl::default()` remains the default
  everywhere); the built-in surface sets it via
  `HttpAdapter::with_ws_op_register_acl`, bare-registry/custom routes
  via the `OpRegisterAcl` request extension (mirroring
  `ChannelsPolicy`/`WsTimeouts`/`OpenableAlpns`). A peer whose
  identity does not satisfy the ACL gets `FORBIDDEN` on the announce.
  Gates: builder path (`FORBIDDEN` scope-less / announce-ok scoped)
  + extension path.

- WS-30: the bare-registry `SessionState` is built by `FromRef` per
  request, so its default-cap semaphore bounds nothing across
  requests (corrects review-002 WS-17's "bounded at 64 sessions"
  claim). New `SessionSlots` request extension carries the shared
  semaphore for routes that need an effective cap; the upgrade
  handler prefers it over the state value. Doc comments corrected
  (`SessionState`, `WsTimeouts`, `ws_upgrade_handler`). Gate:
  cap-1 route → 503 over cap → slot freed on session end.

- WS-32: the built-in openables threading
  (`with_ws_openable_alpns` → `RouterState` → `SessionState` → hook)
  gets its first gate — every Unit-3 gate rode the `OpenableAlpns`
  extension fallback. `builder_path_openables_serve_the_data_channel_
  surface` discovers the openable via `services/list`, opens the
  channel, and round-trips bytes through the builder-built router.

Verification: cargo test 454 passed / 0 failed; cargo test
--all-features 587 passed / 0 failed (+5 gates); clippy (both
configs) clean; fmt clean.

Review: docs/reviews/007-ws-data-channel-surface-review.md
2026-09-05 05:44:28 +00:00
glm-5.3-flash 38738943c7 fix(websocket): WS-28 — bind the channel-0 ConnectionGuard in the task's frame
The WS-26 `ConnectionGuard` was bound inside its `if let` block, so it
dropped microseconds after insertion instead of living for the
channel-0 dispatcher task — `live_connections()` /
`live_connection_count()` were permanently empty for every session
(review 007 WS-28 [major], reproduced empirically; the handle
retention ADR-048 + review-006 record was aspirational at that commit).

Remediation (review 007 Unit 1):

- bind the guard as an `Option<ConnectionGuard>` in the channel-0
  task's frame, mirroring `SessionGuard`'s shape in
  `run_channels_session`; the block comment now describes the real
  scope
- gate `live_connections_visible_mid_session_and_drain_after_teardown`
  — handle visible mid-session (after a completed call proves the
  dispatcher is up), drained after teardown; verified to fail against
  the pre-fix tree and pass with the fix

Verification: cargo test 454 passed / 0 failed; cargo test
--all-features 582 passed / 0 failed; clippy (both configs) clean; fmt
clean.

Review: docs/reviews/007-ws-data-channel-surface-review.md (WS-28)
2026-09-05 05:41:53 +00:00
glm-5.3-flash b36ec49cc1 docs(review 007): fresh-eyes pass over the landed WS data-channel surface
First review whose subject is the landed wiring itself (review 006
Units 2-4, 030c5ef/2053420/64fa10b), not the gap to it.

Findings:
- WS-28 [major] — the WS-26 ConnectionGuard is bound inside the
  `if let` block and drops when it ends, not when the channel-0 task
  ends: live_connections() is permanently empty for every session.
  Reproduced empirically through the live WS path (scratch test,
  run + removed). ADR-048's landed note and review-006's log record
  behavior the code does not have.
- WS-29 [minor] — the op/register ACL override recorded as landed
  (review-006 UP-02, ADR-048) is not implemented; the hook hardcodes
  AccessControl::default() and ChannelsPolicy cannot express an op ACL.
- WS-30 [minor] — the bare-registry default session cap is built per
  request (FromRef) and bounds nothing; corrects review-002 WS-17.
- WS-31 [minor] — install_bootstrap_discovery silently shadows a
  deployment's own services/list on WS sessions (upstream-mandated,
  unrecorded).
- WS-32 [minor] — the router-state openables threading
  (with_ws_openable_alpns) has no gate; every Unit-3 gate rides the
  extension fallback.

Plus non-findings bounding the re-review (UP-01 arm, policy threading,
from_wss exclusion set, extension precedence, gate fidelity) and a
sequenced remediation plan.

Baseline at 64fa10b: 454 / 582 tests, clippy both, fmt, doc — all clean.
2026-09-05 00:46:22 +00:00
glm-5.3-flash 64fa10be31 docs(review 006 Unit 4): spec reconciliation — OQ-05 resolved, WS data-channel docs to the landed state
- OQ-05: deferred → resolved (2026-09-04, review 006 Unit 2+3); the
  consumer-set reframe recorded (WS is also the native-client fallback
  behind hostile NAT/firewall; OQ-04 does not block the wiring).
- ADR-067: status amendment + the v1-cut blockquote gains the Wired
  (2026-09-04) note — per-session-fork shape, openable surface, gates.
- ADR-048: landed-state amendment — §4's hub→browser direction has its
  object (op/register → connection overlay, hub composes via the
  retained Arc<CallConnection>); the op/register ACL posture (UP-02,
  SRV-10 precedent) recorded.
- websocket.md: the step-7 deferral note and the §"Data channels for
  browsers" status block removed (the section now documents the landed
  surface: with_ws_openable_alpns, the OpenableAlpns fallback, cap
  policy, discovery, gates); idle-knob deployment note for silent data
  channels (semantics unchanged; the 60 s default bites more often —
  set None at assembly for long-lived interactive channels).
- Review 003 status → remediated (all findings closed; log in review
  006); its Unit-4 section marked landed.
- alknet-ADR-044 §5 pointer checked: not stale.

Verification: cargo test 454 / 0; --all-features 582 / 0; clippy
(both) clean; fmt clean; doc clean.
2026-09-04 16:17:11 +00:00
glm-5.3-flash 2053420f7d chore(deps): consume alkcall 0.3.1 — list-peers announced-op discovery gate
The alkcall 0.3.1 fix (fd21230, alkhttp review 006 UP-03) lands
PeerCompositeEnv::peer_operations, so services/list-peers now lists
peer-announced ops. Version pin stays 0.3 (semver-compatible); the
lockfile bump carries no source change.

- Extend op_register_served_per_session_and_collision_is_already_exists
  with the discovery assertion that originally surfaced UP-03: after
  the announce resolves, services/list-peers attributes consumer/exec
  to the alice peer entry (fails against 0.3.0, verified by the
  original draft).
- Review 006 UP-03 entry records the 0.3.1 landing (alkcall ADR-030).

Verification: cargo test 454 passed / 0 failed; cargo test
--all-features 582 / 0; clippy (default + all-features, all-targets,
-D warnings) clean; fmt clean; doc clean.
2026-09-04 16:17:07 +00:00
glm-5.3-flash 214fd213ff docs(review 006): remediation log for Unit 2+3; UP-03 filed upstream-side
- Unit 2/Unit 3 recorded as landed (030c5ef): hook rework shape,
  policy threading (the ChannelsPolicy seam the ledger gate caught),
  WS-26 handle retention, from_wss protocol-op exclusion, UP-01, the
  six new gates, and the harness hardening notes (request-id filter,
  flat CallError payload shape).
- UP-02 decided: op/register serves per session with the default ACL
  (SRV-10 posture); the visibility tension resolves as ACL-gate.
- UP-03 [minor, alkcall-side] filed: services/list-peers cannot list
  peer-announced ops — PeerCompositeEnv overrides peer_ids but not
  peer_operations (trait default Vec::new()), so the amendment's
  peer-discovery promise does not resolve on the wire. Discovered by
  the gates; fix lives in alkcall; alkhttp's gate asserts
  overlay-landing + collision semantics instead and is not blocked.
- Unit 4 (docs reconciliation) remains open.

Verification unchanged: cargo test 454/582, clippy both sides, fmt,
doc — clean.
2026-09-04 15:47:48 +00:00
glm-5.3-flash 030c5efa51 feat(websocket): data-channel + op/register wiring (review 006 Unit 2+3)
The WS path wires the alkcall 0.3 per-session mechanisms — the OQ-05
deferred half (review-003 WS-20/21/22/25/26, the decisions WS-24/WS-25
resolved upstream):

- install_channel_zero reworked per the ADR-047 §4 amendment #2 shape:
  fork the deployment's base registry, register the generic channel
  ops (channel/close, channel/control, channel/resources/subscribe —
  WS-21), the deployment's openable ALPNs (ChannelCore::register_openable,
  WS-22), the bootstrap discovery set closed over the fork
  (install_bootstrap_discovery, F-06), and op/register (WS-25; the
  collision set is the fork per review-005 G-03), then dispatch over
  the fork. The session's ChannelsPolicy rides the hook (one policy
  instance across open wrappers and the demux teardown path).
- OpenableAlpn { spec, open_handler } + HttpAdapter::with_ws_openable_alpns,
  threaded RouterState -> SessionState -> hook, with the OpenableAlpns
  request-extension fallback (mirroring ChannelsPolicy/WsTimeouts).
- WsSessions retains the channel-0 Arc<CallConnection> (WS-26) with a
  self-removing guard (ConnectionGuard); live_connections() is the
  deployment-visible surface.
- UP-01: ALREADY_EXISTS maps to 409 Conflict in the gateway error map.
- from_wss import excludes the protocol-session ops (bootstrap set +
  channel lifecycle ops): the fork serves them per session, and proxying
  session-scoped machinery (e.g. channel/close across sessions) would be
  nonsense. Discovery runs first, the filter is the listing minus those
  names.
- adapter_install_channel_zero cfg matches its caller (WS-27); it
  inherits the reworked hook (session ops now served in the from_wss
  test-server producer too).

Gates (Unit 3, tests/ws_upgrade_session.rs; the WS-23 e2e set):
open -> channel_id -> discoverable in services/list -> chunks both
ways -> handler sees bytes; channel/close resolves + ledger decrement;
cap denial (channel:-prefixed); mid-open disconnect teardown; TooLarge
demux resync through the WS path (16 MiB + 1 skip consumed);
op/register announce + overlay-collision + serving-registry-collision
ALREADY_EXISTS through the WS path.

call_and_await now filters by request id and tolerates data-channel
chunks (a prior Sub's trailing call.completed may interleave).

Verification: cargo test 454 (default) / 582 (all-features), clippy
both sides -D warnings clean, fmt clean, doc clean.
2026-09-04 15:47:15 +00:00
glm-5.3-flash 90790374fa docs(review 006): alkcall 0.3.0 consequence review — WS-24/25 resolved upstream, residual enumerated
Records the review pass of alkcall 0.3.0 against this crate:

- WS-24 (dispatch-resolution mechanism) and WS-25 (client-side op
  registration) verified resolved upstream — per-session fork (alkcall
  ADR-047 §4 amendment #2) + op/register (alkcall ADR-022 amendment
  2026-09-03 + 2026-09-04 collision sub-amendment); the G-01 serving-
  loop concurrency rework lands here via the bump alone.
- One new finding: UP-01 [minor] — ALREADY_EXISTS (new 0.3 protocol
  code) unmapped in the gateway error table (would 500); fix rides
  Unit 2. UP-02 records the op/register ACL posture decision for
  Unit 2.
- WS-20/21/22/26/27/23 re-verified still open, now unblocked; the
  remediation plan re-sequences (Unit 2 wiring with the concrete
  fork shape, Unit 3 gates + two upstream-mirroring additions,
  Unit 4 docs).

Baseline gates at df86f89: cargo test 453/575, clippy both sides,
fmt, doc — all clean.
2026-09-04 14:58:43 +00:00
glm-5.3-flash df86f89440 docs(review 003): land the Unit-1 re-point; extend it to alkcall review 005 + 0.3.0
Commits the re-point edits left uncommitted in the working tree
(5b62307's follow-through; alkcall review 005 verified these lines at
that tree), updated to the post-review-005 state:

- ADR-048 reconciliation note gains the 2026-09-04 update: alkcall
  review 005 remediated the landed mechanisms (serving-loop
  concurrency G-01/G-02, op/register collision policy G-03, spec
  round-trip G-04, bootstrap-list alignment G-05) and alkcall 0.3.0
  shipped them; alkhttp now consumes 0.3. The ADR-022 collision
  sub-amendment binds here: a peer-announced op never shadows the
  serving side's own registrations — the WS session's op/register
  handler gates on the session fork.
- OQ-05 resolution gains the same dated update and extends the
  cross-references to alkcall reviews 004-005.

What remains here is still alkhttp-side wiring only (review 003
Unit 2).
2026-09-04 14:55:23 +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 5b62307be9 docs(review 003): Unit 1 re-pointed at alkcall review 004; bootstrap-op candidate recorded
The alkcall decision work (WS-24 dispatch-resolution mechanism, WS-25
client-side op registration) now lives upstream as alkcall review 004.
Unit 1 records the leading candidates and their alkhttp consequences:

- WS-24 -> option (a), per-session base registry (the only
  wire-proven dispatch shape; fork surface = alkcall F-02)
- WS-25 -> channel-0 bootstrap op (op/register as an assumed op in
  the bootstrap set; requires the alkcall client serving half, F-04)
- discovery composition: services/list on the fork + peer-registered
  ops via the already-built services/list-peers

Consumer-set reframe from WS-23 unchanged; no findings added or
removed.
2026-09-03 14:42:50 +00:00
glm-5.3-flash 19e30c9769 docs(review 003): WS data-channel wiring gap drill-down
Focused review of the OQ-05 deferral (review-001 WS-03): what is
missing to wire browser/native data channels over WS, the deferral
rationale check, and the design gaps found behind the 'nothing new
to design' assumption.

Findings (continuing review-002 numbering):
- WS-20..22 [major]: mechanical wiring gap — install_channel_zero
  discards the ChannelManager, generic channel lifecycle ops never
  registered, no openable-ALPN deployment surface
- WS-23 [minor]: no browser-opened-channel e2e test; OQ-05 reopen
  trigger reframed (native WS consumers are not blocked on OQ-04)
- WS-24 [major, cross-crate]: top-level dispatch never consults the
  connection overlay — the ADR-047 §4 amendment mechanism cannot
  resolve open ops on the wire (needs an alkcall decision)
- WS-25 [major]: no wire mechanism for client-side op registration —
  ADR-048 browser-side bidirectionality is undesignable as specified
- WS-26 [major]: no retained live connection handle; hub cannot
  reach a session's overlay or push toward it
- WS-27 [minor]: dead-code-gated test hook cleanup

Includes a non-findings section (channel-id split, demux hardening,
open-op wrapper completeness, idle-knob posture) and a 4-unit
remediation plan sequenced so the alkcall decision task (Unit 1)
gates the alkhttp wiring shape (Unit 2).

Verification: cargo test (453) / --all-features (575), clippy
(all-targets, both feature sets), fmt — all clean at 58665f2.
2026-09-03 08:31:44 +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