Commit Graph
9 Commits
Author SHA1 Message Date
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 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 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 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 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