feat: allocation moves into the channels establisher (alkcall 0.6.0 / review 007 R-01) — bump to 0.3.0

- Bump alkcall 0.5.0 -> 0.6.0 (Establishment plan payload, ADR-049
  amendment 2); alktty 0.2.0 -> 0.3.0 (breaking channels-path
  allocation-failure shape)
- make_tty_establisher runs backend.allocate; failure maps to
  EstablishmentError::DialFailed (channel:open_failed reason
  dial_failed); the TtyHandle crosses to the pump handler via a
  private per-open AllocatedHandle one-shot slot (the handle is not
  Sync — it cannot be the ChannelPlan directly)
- make_tty_open_handler gains the Option<ChannelPlan> parameter; a
  plan drives the new drive_session_pre_allocated (pumps only), a
  None plan falls back to drive_session_pre_negotiated (inline
  validate-and-allocate — defense-in-depth for no-establisher
  registrations)
- tty_open_spec's channel:open_failed ErrorDefinition declares
  dial_failed (four reachable reasons)
- Pinned in-band allocate test flipped:
  allocate_failure_fails_open_as_dial_failed (end-to-end, no channel
  survives); establisher unit gate for the plan slot + failure
  mapping
- ADR-010 amended (§2A; §2 kept as historical record), tty-adapter.md,
  session/channels/adapter docs, CHANGELOG, AGENTS.md alkcall pin
  updated

Verification: cargo test (113) + --all-features (137), clippy
-D warnings (native + wasm32, default + all-features), fmt, doc,
wasm32 check — all clean
This commit is contained in:
glm-5.3-flash committed 2026-09-07 09:53:57 +00:00
1 parent 3352a02dd5
commit af9dbaedea
10 files changed
+434 -147

No files matched your search

+26
View File
@@ -253,6 +253,32 @@ pub async fn drive_session_pre_negotiated(
}
}
/// Drive a `alk/tty` session whose negotiation AND allocation already
/// happened out of band — the channels path with an establisher
/// (alkcall 0.6, ADR-010 as amended). The establisher validated the
/// request and ran `backend.allocate`; its `TtyHandle` arrived via the
/// establishment plan (`AllocatedHandle`, taken by the open handler).
/// The raw-chunk data plane starts immediately; nothing is read or
/// written before the pumps.
///
/// Not public API: the only caller is the channels open handler. A
/// consumer that somehow reaches a pre-allocated stream without the
/// producer-side establisher (no-establisher registration) goes
/// through [`drive_session_pre_negotiated`] instead, whose inline
/// validate-and-allocate keeps the in-band error-frame fallback.
pub(crate) async fn drive_session_pre_allocated<W, R>(
client_send: W,
client_recv: R,
handle: TtyHandle,
) where
W: AsyncWrite + Send + Unpin + 'static,
R: AsyncRead + Send + Unpin + 'static,
{
if let Err(e) = pump_session(client_send, client_recv, handle).await {
debug!("tty: session ended with error: {e}");
}
}
/// Validate a parsed `NegotiateRequest`, select the backend, run the
/// ADR-050 ownership check, and allocate. Shared by the direct
/// (wire-negotiated) and channels (pre-negotiated) paths. Failures are