feat(dispatch): land the parse-only dispatch + the fail-closed decline core (w2-dispatch-decline-core)

- src/dispatch.rs: the ExecRoute decision, the skeleton exec-parse
  probe (service prefix + path shape; wave 3 replaces with the full
  grammar), the wire-reason shapers (AdministrativelyProhibited for
  unfeatured/never-feature opens, ConnectFailed for the tunnel seam
  stub), 7 probe unit rows
- src/handler.rs: channel_open_* gates per the feature graph (session
  ∨ git; tunnel; x11/auth-agent never), parse-only exec_request
  dispatch before any allocation, session-row routes, request-level
  declines (subsystem all-names with the sftp OQ-13 and git named
  classes, env per OQ-09, x11/agent, the four listen requests), the
  named wave-3 seam stubs; decline-first-alloc-never structural;
  module docs carry the decline-core contract incl. the inherited
  auth-agent-open upstream note
- tests/dispatch_core.rs: 26 Contract-stamped decline-matrix rows per
  feature build driven through the loopback harness (none / git-only /
  session-only / tunnel-only / all-features + shared never-feature
  rows)
- tests/common/harness.rs: extended helper vocabulary (tunnel/x11
  opens, pty/env/x11/agent requests, listen requests) — discharges
  the w2-loopback-harness live-rows note
- tests/loopback_harness.rs: the skeleton decline-only session-open
  row cfg-pinned to the featureless builds it describes

Verification: cargo test (91 rows, default build); per-feature
dispatch_core rows (git 11 / session 10 / tunnel 4 / all 8 / sftp 3);
cargo test --all-features; cargo clippy --all-targets -- -D warnings
(and --all-features); cargo fmt --check; cargo doc --no-deps
This commit is contained in:
glm-5.3-flash committed 2026-10-28 09:04:42 +00:00
1 parent 3b77193e85
commit 68d3723f6a
7 files changed
+1543 -12

No files matched your search

+81
View File
@@ -56,6 +56,16 @@
//! russh-verbatim shape ([`AuthResult`], [`Error`],
//! [`ChannelMsg`]) the rows match on directly.
//!
//! The helper set grows with the rows it serves: `w2-loopback-harness`
//! landed the auth/session/exec/shell/subsystem vocabulary, and
//! `w2-dispatch-decline-core` extended it with the decline-matrix
//! vocabulary (the tunnel/x11 opens, the pty/env/x11/agent-forward
//! requests, the listen requests) — its recorded expectation that the
//! "session-request and exit-status/close helpers are exercised by
//! construction this wave ... their live rows arrive with
//! `w2-dispatch-decline-core`" is discharged by exactly that
//! extension, not by a harness rewrite.
//!
//! Like the doubles: test functions are *rows* carrying the greppable
//! **`Contract stamp:`** doc markers (see the common module's doc).
@@ -264,6 +274,40 @@ pub async fn open_session_channel(
client.channel_open_session().await
}
/// Opens a `direct-tcpip` channel — the tunnel open helper (`ssh -L`
/// / `ssh -D` traffic). The open-failure shape is the `Err` verbatim,
/// the decline-matrix rows' reason surface.
pub async fn open_direct_tcpip(
client: &Handle<HarnessClientHandler>,
host_to_connect: &str,
port_to_connect: u32,
) -> Result<Channel<Msg>, Error> {
client
.channel_open_direct_tcpip(host_to_connect, port_to_connect, "harness-originator", 0)
.await
}
/// Opens a `direct-streamlocal` channel — the unix-socket forward
/// helper. The open-failure shape is the `Err` verbatim.
pub async fn open_direct_streamlocal(
client: &Handle<HarnessClientHandler>,
socket_path: &str,
) -> Result<Channel<Msg>, Error> {
client.channel_open_direct_streamlocal(socket_path).await
}
/// Opens an x11 channel — the never-feature open helper (ADR-003 §5).
/// The open-failure shape is the `Err` verbatim.
pub async fn open_x11_channel(
client: &Handle<HarnessClientHandler>,
originator_address: &str,
originator_port: u32,
) -> Result<Channel<Msg>, Error> {
client
.channel_open_x11(originator_address, originator_port)
.await
}
/// Sends an exec request over a channel (`want_reply` set — the
/// success/failure shape rides [`ChannelMsg::Success`]/[`ChannelMsg::Failure`]
/// through [`next_message`]).
@@ -281,6 +325,43 @@ pub async fn request_subsystem(channel: &Channel<Msg>, name: &str) -> Result<(),
channel.request_subsystem(true, name).await
}
/// Sends a pty request over a channel (`want_reply` set — the pty row
/// rides the standard success/failure observation).
pub async fn request_pty(channel: &Channel<Msg>) -> Result<(), Error> {
channel.request_pty(true, "xterm", 80, 24, 0, 0, &[]).await
}
/// Sends an env request over a channel (`want_reply` set — the OQ-09
/// unconditional-decline rows' observation).
pub async fn request_env(channel: &Channel<Msg>, name: &str, value: &str) -> Result<(), Error> {
channel.set_env(true, name, value).await
}
/// Sends an x11-req request over a channel (`want_reply` set — the
/// never-feature request rows).
pub async fn request_x11(channel: &Channel<Msg>) -> Result<(), Error> {
channel
.request_x11(true, false, "MIT-MAGIC-COOKIE-1", "harness-cookie", 0)
.await
}
/// Sends an agent-forwarding request over a channel (`want_reply` set
/// — the never-feature request rows; ADR-003 §5).
pub async fn request_agent_forward(channel: &Channel<Msg>) -> Result<(), Error> {
channel.agent_forward(true).await
}
/// Requests a `tcpip-forward` listen (`-R` ingress) — the
/// success/failure shape is the result verbatim
/// ([`Error::RequestDenied`] on a declined listen).
pub async fn tcpip_forward(
client: &Handle<HarnessClientHandler>,
address: &str,
port: u32,
) -> Result<u32, Error> {
client.tcpip_forward(address, port).await
}
/// Observes the next channel message — `None` after the channel has
/// closed (russh's EOF-of-conversation shape).
pub async fn next_message(channel: &mut Channel<Msg>) -> Option<ChannelMsg> {