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.
19 KiB
Review 006 — alkcall 0.3.0 consequence review (WS-24/WS-25 upstream, alkhttp residual)
Status
Verified, open for Unit 2. One new finding (UP-01); the 0.3 bump
committed and verified (3dee46a).
Scope
Consequence review of alkcall 0.3.0 (published 2026-09-04 — the remediation of alkcall reviews 004–005, which is the upstream resolution of this repo's review-003 findings WS-24/WS-25) against this crate. The pass answers three questions:
- What does the 0.3 bump itself cost here (source breaks, behavior changes)?
- Which review-003 findings are now resolved upstream, and which remain alkhttp-side work?
- Did the upstream remediation introduce anything this crate must absorb (new protocol codes, new wiring contracts, new decisions)?
Sources read: alkcall review 004 (docs/reviews/004-…md, remediated)
and review 005 (docs/reviews/005-…md, resolved G-01..G-05), the
0.3.0 changelog, the ADR amendments (alkcall ADR-047 §4 amendment #2,
ADR-022 amendments 2026-09-03 + 2026-09-04), and the published
0.3.0 crate source. Every claim below verified in source at this
tree (df86f89, consuming alkcall 0.3.0) or the published crate.
Findings use the new prefix UP (upstream-consequence); review 003's
WS numbering is referenced for continuity.
Baseline verification (this pass)
cargo test → 453 passed, 0 failed
cargo test --all-features → 575 passed, 0 failed
cargo clippy --all-targets -- -D warnings → clean
cargo clippy --all-features --all-targets -- -D warnings → clean
cargo fmt --check → clean
cargo doc --no-deps → clean
Verified after the 0.2 → 0.3 bump (3dee46a). The bump cost was
two source-break classes, both mechanical:
ChannelClient::take_call_connectionnow returnsOption<Arc<CallConnection>>(was a bareCallConnection) —WssSession::connectdropped itsArc::newre-wrap (src/adapters/from_wss.rs:268-274).OperationRegistry::register,ChannelOperations::register_on, andChannelCore::register_openablenow take&OperationRegistry(was&mut) — 51 stalemutbindings dropped viaclippy --fixacrosssrc/adapters/{from_wss,to_mcp, to_openapi}.rs,src/gateway/routes.rs,src/server/adapter.rs, andtests/.
The &self-registration change is the interior-mutability change
that makes the per-session fork surface possible; for every existing
alkhttp call site it is source-compatible (reborrow). The
registration() → owned and list_operations() → owned return-type
changes required no edits here (call sites already cloned through
the borrow or consumed by value-compatible iteration — verified by
the clean build).
Verdict
- WS-24 and WS-25 are resolved upstream. The two design gaps
review 003 Part B identified are now mechanized in alkcall 0.3.0
and decided in its ADRs: the per-session fork is the
dispatch-registry mechanism (alkcall ADR-047 §4 amendment #2 —
review-003 option (a), the wire-proven shape), and
op/registeris the client-side registration mechanism (alkcall ADR-022 amendment 2026-09-03 — review-003's bootstrap-op candidate). The alkhttp-side consequences of review-003 Unit 1's candidates are exactly what landed. - One upstream remediation result lands here for free: review
005 Unit 1 mechanized the accept-side pending-resolution arms into
run_loop_single_stream(the loop our WS channel-0 dispatch runs). Pre-0.3, an accept-side nested-composing handler (afrom_callimported-op stub riding the WS connection) could deadlock against the inline dispatch; post-0.3 the loop spawns Once invocations and Sub pumps, so the G-01 hazard class is shut for WS sessions by the bump alone — no alkhttp code involved. - The remaining review-003 findings are all still open and now
unblocked (WS-20/21/22/26 mechanical, WS-27 cleanup, WS-23
tests): the hook still discards the
ChannelManager(src/websocket/upgrade.rs:255), no channel ops / openables / bootstrap discovery are registered, no deployment surface declares openable ALPNs, and no live connection handle is retained. All grep-verified at this tree. - One new finding (UP-01): alkcall 0.3 introduced the
ALREADY_EXISTSprotocol code; this crate's gateway error table has no arm for it and would map it to 500. Unreachable today (onlyop_register_handleremits it), load-bearing the moment Unit 2 wiresop/register. - One wiring contract Unit 2 must honor (UP-02, recorded as a
decision point, not a defect): the
op/registercollision policy binds the WS session's handler to the session fork.
Severity legend
Same scale as review 003: [major] — a decided behavior is missing/wrong or a real hazard; [minor] — drift, convention violation, or doc/spec inconsistency with no correctness impact.
Part A — What 0.3.0 resolves for this crate
WS-24 [was major, cross-crate] — dispatch-resolution mechanism → RESOLVED upstream
alkcall ADR-047 §4 amendment #2 (2026-09-03) decides option (a): the
install_channel_zero hook forks the deployment's base registry,
registers the per-session ops on the fork (ChannelOperations:: register_on, ChannelCore::register_openable,
install_bootstrap_discovery — the last closed over the fork so
services/list sees per-session openables, review-004 F-06), and
dispatches channel 0 over the fork. The connection overlay remains
the peer-announced-op landing zone and nested-invocation target, not
the dispatch-resolution path. The reference shape is alkcall's
fork_registry_open_op_resolves_and_is_discoverable gate
(alkcall/src/channels/client.rs:1994 — fork → register_openable
→ install_bootstrap_discovery → Dispatcher::new(fork, …)), which
is the shape Unit 2 must reproduce in install_channel_zero.
Upstream also resolved the fork's discovery half (review-004 F-06):
install_bootstrap_discovery registers services/list,
services/list-peers, and services/schema closed over the fork
itself, so per-session openables are discoverable without a
re-registration walk. The bootstrap set is closed at four with
op/register (alkcall ADR-022 amendment, services/list-peers
added 2026-09-04 per review-005 G-05).
alkhttp consequence: none to code yet; Unit 2 consumes it.
WS-25 [was major, cross-crate] — client-side op registration → RESOLVED upstream
alkcall ADR-022 amendment (2026-09-03) decides the bootstrap-op
mechanism: op/register (registry::op_register module) — a peer
announces an op spec over channel 0; the hub's per-session handler
rebuilds the spec, wraps it as a forwarding stub that nested-calls
back over channel 0, and lands it in the connection overlay via
register_imported (forced Visibility::Internal, provenance
FromCall). The wire stays the six call.* envelope kinds.
Collision policy (2026-09-04 sub-amendment, review-005 G-03): an
announced op may replace other announced ops (replace governs)
but never the serving side's own registrations — ALREADY_EXISTS
regardless of replace; the handler gates on the serving registry
first, then the overlay.
The serving half it composes on (Dispatcher::serve_single_stream,
opt-in via ChannelClient::from_connection_with_serving) landed
with review-005 Unit 1's concurrency rework: Once invocations, Sub
pumps, and sink response writers are spawned in both single-stream
loops, so same-connection nested composition (the flagship
hub-composes-peer-op flow) resolves concurrently instead of
deadlocking to the 30 s sweeper (review-005 G-01, empirically
verified upstream with a since-removed probe, productized as two
5s-bounded gates).
alkhttp consequences: Unit 2 wires op/register on WS sessions
by registering op_register_spec(acl) +
op_register_handler(connection, fork) on the per-session fork
(the collision set is the fork — exactly what the session
dispatches over, mirroring the upstream gates' production shape).
Two additional facts from review 005 apply:
- The channel-0
Connectionmust carry the peer identity forcompose_root_envto attach the connection's overlay (keyed byidentity.id). alkhttp's hook already does this (src/websocket/upgrade.rs:264— identity propagated from the upgrade'sAuthContext); verified correct as-is. - The serving loop's concurrency means a hub handler that composes an announced op resolves live (no sweeper); no alkhttp-side scheduling work is needed.
ADR-048's browser bidirectionality promise is now mechanized on the
hub half; the browser half (announcing via WS framing) is a
client-side concern with no alkhttp code beyond serving the op.
The re-point edits in ADR-048/OQ-05 (committed df86f89) record
this.
Fixed-upstream items this crate inherits
- Accept-side nested-composition hazard (review-005 G-01's
second consequence): mechanized shut by the pending-resolution
arms now in
run_loop_single_stream— inherited by the bump, no alkhttp code. resource_id_pathwire round-trip (review-005 G-04): afrom_call-imported or announced op declaring ownership-scoped resource extraction previously rebuilt withresource_id: None(ACL checks ran without the resource id). Both round-trip halves now carry the field.from_wss's import path inherits the fix.- Head-of-line blocking / interleaved directions: a serving
side's outbound calls resolve while it serves a Sub (the
interleaved-directions gate upstream) — relevant to any future
serving-enabled
from_wss(see Part C).
Part B — Findings at this tree
UP-01 [minor] — The ALREADY_EXISTS protocol code is unmapped in the gateway error table
Verified: YES. alkcall 0.3 added CallError::already_exists
("ALREADY_EXISTS", non-retryable —
alkcall-0.3.0/src/protocol/wire.rs:124) for the op/register
collision policy; its own ADR-022 amendment records the code.
alkhttp's status map (src/gateway/error.rs:57-80) has no arm for
it: NOT_FOUND, FORBIDDEN, INVALID_INPUT,
INVALID_OPERATION_TYPE, TIMEOUT, INTERNAL, and HTTP_*
prefixed codes are mapped; anything else falls to STATUS_INTERNAL
(500). alkcall's ADR-016 code list (six codes) was not amended for
the seventh — upstream doc drift, noted for that repo.
Reachability today: none — the only emitter is
op_register_handler, which no alkhttp path invokes yet (grep
verified; the gateway dispatches base-registry ops directly). It
becomes reachable exactly when Unit 2 wires op/register on WS
sessions, at which point a collision rejection would surface to
wire callers as 500 with an ALREADY_EXISTS body instead of a
conflict status. Because the collision path is also how a peer
experiences the reconnect-reannounce contract (replace refused
for serving-registry names), fidelity matters there.
Fix (Unit 2, ride-along): map ALREADY_EXISTS → 409 Conflict in
call_error_to_http_status_with_identity (plus the test arm),
matching ADR-023's HTTP_<status> discipline for the new code.
One-line change + test; no consumer breaks (the code is new).
UP-02 [minor, decision point] — op/register's AccessControl on the WS surface needs a decided default
Not a defect — a decision Unit 2 cannot avoid. alkcall's
op_register_spec(access_control) takes the ACL as a parameter; its
doc notes the default (AccessControl::default()) lets any peer
register, and the op is Mutation/External-typed. This crate's
convention (AGENTS.md §13, ADR-015): adapter-registered ops are
Visibility::Internal by default — but op/register cannot be
Internal on the wire surface (the peer must call it; Internal ops
resolve spec-404 to wire callers). The analogous precedent here is
the built-in gateway's NoCap posture for channel opens (review-001
SRV-10: crate default is permissive, deployments gate via the
ChannelsPolicy extension). The consistent shape: register
op/register on the per-session fork with AccessControl::default()
on the built-in surface and let an assembly-layer override pass a
stricter ACL the same way ChannelsPolicy/OpenableAlpn flow —
record the posture in the Unit-2 task and in ADR-048's amendment
note when the wiring lands.
WS-20/WS-21/WS-22/WS-26 [major] — unchanged, now unblocked
Re-verified at this tree; all four stand as review 003 found them:
install_channel_zerostill discards the manager (src/websocket/upgrade.rs:255—_managerunused); noChannelCore, noChannelOperations::register_on(grep: zero callers in this crate), no openables.- No
OpenableAlpnsurface exists (src/server/adapter.rsbuilders unchanged:with_decoy/with_extra_routes/with_ws_max_sessions/with_ws_idle_timeout). - No live
Arc<CallConnection>handle is retained by the session (the hook moves channel 0's connection into the spawned task);WsSessionsstill tracks pump handles only.
The fix shape from review 003 Unit 2 stands, now with the upstream
mechanism named concretely: per-session fork() in the hook →
ChannelOperations::register_on(&fork) → openables via
register_openable(spec, handler, &fork, auth) →
install_bootstrap_discovery(&fork) → op_register_spec +
op_register_handler(Arc<CallConnection>, fork) → dispatch over the
fork (Dispatcher::run_loop_single_stream unchanged as the loop).
The OpenableAlpn list + with_ws_openable_alpns threading
(RouterState → SessionState → hook, request-extension fallback
mirroring ChannelsPolicy) is unchanged, as is the WS-26
handle-retention design (eviction hooks into WsSessions).
WS-27 [minor] — unchanged; folds into the Unit-2 hook rework
adapter_install_channel_zero (src/websocket/upgrade.rs:290-295)
is still #[allow(dead_code)] with its only caller test-gated
(src/adapters/from_wss.rs test server). The rework gives both
callers a real hook; fold the cfg cleanup there.
WS-23 [minor] — unchanged; Unit 3's e2e gates gain two upstream-mirroring gates
The browser-opened-channel e2e test is still absent (no test opens a
data channel through a live WS session). Unit 3's five scenarios
stand as written. Two gates to add, mirroring what review 005
taught: services/list on a live WS session lists the per-session
openable (the F-06 shape), and the op/register announce → hub
nested-composition → routes-back-to-consumer flow (the stub path —
the one review-005's original gate missed and G-02 called out).
Part C — Noted, not findings
- Connect-side serving for
from_wss: alkcall 0.3'sfrom_connection_with_servingmakes the WSS consumer half capable of serving inbound calls (the from_wss session could answer hub→consumer calls).from_wsskeeps the pure-consumer default (from_connection, resolution-only pump — verified unchanged); opt-in serving is a deliberate later decision (it changesfrom_wss's security posture: a dial would then execute inbound requests against a caller-chosen registry). Recorded here so the opportunity is visible; no finding, no unit. op/registerforced-Internal semantics vs AGENTS.md §13: the announced op landsInternal/FromCallon the hub — consistent with the adapter-registered-ops-are-Internal convention (it is composition material, not wire-callable from the hub side). No conflict; noted to preempt an apparent tension.list_operationsreturnsExternalonly — theto_openapi/to_mcpprojections and the gateway/searchcontinue to see exactly the External set; unchanged from 0.2.- Upstream doc drift (alkcall-side, not ours): ADR-016's
protocol-code list ("six codes", last amended by ADR-021) does not
name
ALREADY_EXISTS. The 2026-09-04 ADR-022 collision sub-amendment records the code's use; ADR-016's list is stale. Flagged for the next alkcall doc pass; UP-01 is the alkhttp-side half of the same gap.
Remediation plan (alkhttp side; supersedes review 003's plan where noted)
Review 003's Units 1 and 4 are partially closed by upstream; the remaining work re-sequences as:
Unit 2 — alkhttp wiring (WS-20/21/22/26/27 + UP-01) — next
OpenableAlpn { spec, open_handler }+HttpAdapter::with_ws_openable_alpns(...), threadedRouterState→SessionState→run_channels_session→ hook, with a request-extension fallback (mirrorChannelsPolicy).- Hook rework per the upstream reference shape: fork → channel ops
→ openables → bootstrap discovery →
op/register(ACL per UP-02's decided posture) → dispatch over the fork; retain theArc<CallConnection>in aWsSessions-evicted registry (WS-26);adapter_install_channel_zerocfg cleanup (WS-27). - UP-01:
ALREADY_EXISTS→ 409 in the gateway error map + test.
Gate: a live WS session lists its openable in services/list; an
open op on channel 0 returns a channel_id; op/register collides
loudly against fork-registered names (409 over the WS path).
Unit 3 — e2e tests (WS-23) — after Unit 2
Review 003's five scenarios stand, plus the two upstream-mirroring gates named in Part B (openable discoverable on the live session; announce → nested composition → routes back).
Unit 4 — spec reconciliation (docs) — after Unit 2
Review 003's list stands (OQ-05 resolution, ADR-067/ADR-048 notes,
websocket.md status block, idle-knob deployment note), with the
op/register ACL posture recorded per UP-02.
Verification log (this pass)
- Bump verified empirically:
cargo check(default + all-features) surfaced exactly the two break classes; post-fix gates all green (453 / 575 / clippy both / fmt / doc). - WS-24/WS-25 resolutions read in the published 0.3.0 crate source
(
registry::op_registerhandler + collision gate;Dispatcher::serve_single_stream;install_bootstrap_discovery;OperationRegistry::fork) and in the upstream ADR amendment texts; the reference fork shape read atalkcall/src/channels/client.rs:1988-2130. - Review-003 residual claims re-verified at this tree: hook
discards manager (
upgrade.rs:255), zeroregister_oncallers, no openable surface, no retained connection handle, WS-27 caller census unchanged. - UP-01 verified: no
ALREADY_EXISTSarm insrc/gateway/error.rs:57-80; emitter census in 0.3.0 =op_register.rsonly; fall-through confirmed toSTATUS_INTERNAL. - UP-02 verified:
op_register_specsignature and its default-ACL doc note; AGENTS.md §13 vs wire-callable tension resolved against the SRV-10 precedent (permissive crate default + extension override). - Cross-repo state verified: alkcall review 005 resolved
(G-01..G-05 remediation log), 0.3.0 published with
cargo semver-checks196 checks against 0.2.0 (changelog's Changed section matches the two source-break classes this crate experienced).