feat(e2e): client-direction real-sshd e2e (w5-e2e-client)
The wave-5 client-direction real-tool e2e: a dedicated `tests/e2e_client.rs` binary dialing a per-row spawned real OpenSSH server with the shipped crate — exec (exit-status parity through real reaping), the direct-tcpip dial, the `-R` leg (port-0 mint + accepted arrival + data leg + cancel tearing the real listen down + unknown- cancel ListenRefused), and the decline rows (sftp placeholder, host-key mismatch hard-decline, server-refused direct-tcpip with the connection staying usable). Fixture shape decided + recorded in the task file: per-row spawned sshd, minted ed25519 host key, publickey-only knobs, the decrypt-at-dial vault posture, the case-1 pin posture. No src/ changes; every row check-gated skipped-with-reason and deadline-bounded. Verification: `scripts/matrix.sh` green (cargo test per build none/git/ session/tunnel/sftp/--all-features — e2e_client rides 2/2/3/5/2/7 rows, clippy x2 `-D warnings`, fmt, doc), plus 10 consecutive all-features e2e_client runs green. taskgraph validate: 42 tasks valid.
This commit is contained in:
1 parent
567a34a5e1
commit
69d888a231
2 files changed
+1037
-8
No files matched your search
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: w5-e2e-client
|
||||
name: Wave 5 — real-tool e2e, client direction (the door against a real sshd)
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [review-wave-4]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
@@ -50,16 +50,16 @@ matrix task's binaries), under the check-gated
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] The sshd fixture lands (spawned real server, ed25519 host +
|
||||
- [x] The sshd fixture lands (spawned real server, ed25519 host +
|
||||
user keys, the policy pin posture); its shape decided +
|
||||
recorded
|
||||
- [ ] Exec, direct-tcpip, and the `-R` leg (port-0 mint + accepted
|
||||
- [x] Exec, direct-tcpip, and the `-R` leg (port-0 mint + accepted
|
||||
arrival + cancel) green against real sshd (or reasoned-skipped)
|
||||
- [ ] The decline rows green: sftp placeholder, unfeatured
|
||||
- [x] The decline rows green: sftp placeholder, unfeatured
|
||||
direct-tcpip (connection stays usable), host-key mismatch
|
||||
hard-decline
|
||||
- [ ] Every finding fixed in-task or booked for the gate (recorded)
|
||||
- [ ] `cargo test` (+ the builds the new binary rides), clippy ×2
|
||||
- [x] Every finding fixed in-task or booked for the gate (recorded)
|
||||
- [x] `cargo test` (+ the builds the new binary rides), clippy ×2
|
||||
(`-D warnings`), fmt, `cargo doc --no-deps` green
|
||||
|
||||
## References
|
||||
@@ -80,8 +80,59 @@ matrix task's binaries), under the check-gated
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
**The sshd fixture decided**: `tests/e2e_client.rs` (the new binary), reusing `tests/common` — the
|
||||
wave-4 client binaries stay single-writer per the decomposition's file map; this task edited only
|
||||
its own binary (`tests/e2e_client.rs`, an in-file `support` module). **Fixture shape: per-row
|
||||
spawned real `sshd`** — each row's config knobs differ (`AllowTcpForwarding` yes/no) and each row
|
||||
dials its own server, so a shared per-binary instance buys nothing; per-row isolation (own workdir,
|
||||
own minted ed25519 host key via `ssh-keygen`, own probe-verified port from the e2e-server's
|
||||
monotonic allocator posture) beats the spawn cost. Knob set: publickey-only, `StrictModes no` (the
|
||||
throwaway workdir carries none of the real home-dir hygiene), `UsePAM no`, `UseDNS no`,
|
||||
`PidFile none`, `PermitRootLogin prohibit-password`, host key + authorized_keys (fixture `alpha`'s
|
||||
public blob) at absolute paths, per-row `AllowTcpForwarding`. Readiness is a bounded TCP probe; a
|
||||
server that never comes up is the row's **reasoned skip** with the server's own `-e` log tail as
|
||||
the reason (worked as non-root in this environment — verified against OpenSSH 9.6p1). The dial
|
||||
rides the decrypt-at-dial path over the in-memory vault double (`VaultKeySource` over `TestVault`,
|
||||
`alpha` sealed) and the case-1 pin posture (`MemHostKeyPolicy::pin`) accepts only the minted host
|
||||
fingerprint.
|
||||
|
||||
**Row inventory** (all check-gated, `#[cfg(unix)]` + feature-gated per row group; deadline-bounded
|
||||
end to end — the POC-1 §5 posture; `Contract stamp:` markers cite `client.md` / `reverse-runner.md`):
|
||||
|
||||
| Row | Build(s) | What it pins |
|
||||
|---|---|---|
|
||||
| `exec_row::real_sshd_exec_pumps_streams_and_reports_the_exit_status` | session (+all) | the wave-4 double-driven exec row re-landed: stdout/stderr separated through a real server, the **nonzero** exit (3) reported in-band last — the real server's reaping, parity not a canned 0; the case-1 pin accept decision on record against the really-presented key |
|
||||
| `direct_tcpip_row::real_sshd_direct_tcpip_round_trips_a_live_tcp_connection` | tunnel (+all) | the `-L`-shaped dial through a real server's forwarding into a live loopback echo server, bytes end to end |
|
||||
| `reverse_rows::real_sshd_port_zero_mint_serves_the_accepted_arrival_and_the_data_leg` | tunnel (+all) | the port-0 mint surfaces the actually-bound port (verified by dialing it), the server-initiated `forwarded-tcpip` arrives into the installed acceptor, the external dialer's bytes round trip — the reverse-runner consumer pattern end to end |
|
||||
| `reverse_rows::real_sshd_cancel_tears_the_listen_down_and_unknown_cancels_refuse` | tunnel (+all) | explicit-port listen actually bound; the listener handle's `cancel()` frees the **real** bound port (later dials refused); a stateless cancel of the unknown listener is `ListenRefused`; connection stays usable |
|
||||
| `declines::real_connection_sftp_placeholder_declines_with_the_connection_intact` | **every build** | the OQ-13 placeholder against a real authenticated connection: typed decline before any wire op, connection intact |
|
||||
| `declines::real_presented_key_mismatch_hard_declines_and_the_right_pin_dials` | **every build** | the wrong-pinned policy hard-declines the dial (`DialError::HostKeyRejected`), the policy log records the **real** fingerprint as rejected, and the correctly-pinned dial to the same server succeeds — the decline is the policy's decision, not the server's |
|
||||
| `unfeatured_direct_decline::real_server_refused_direct_tcpip_declines_and_the_connection_stays_usable` | tunnel+session (all-features) | a real server with `AllowTcpForwarding no` refuses the typed open → `OpenDeclined(Prohibited)`, and a following exec is served — the connection-stays-usable fact end to end |
|
||||
|
||||
**Decisions recorded** (for the wave-5 gate):
|
||||
|
||||
- The "connection stays usable" decline row is gated `tunnel` **and** `session` (rides
|
||||
`--all-features` only): the post-decline exec is the stays-usable proof's vehicle, and exec is
|
||||
a `session`-gated op. Under tunnel-only builds the row is absent; the fake-double mirror
|
||||
(`tests/client_ops.rs`) carries the tunnel-only stays-usable rows.
|
||||
- The sftp and host-key-mismatch rows run in **every** build (feature-free ops on
|
||||
`SshConnection`), so even the no-feature matrix build exercises two real-server rows.
|
||||
- The fixture skips are honest: no `sshd` in the environment / no `ssh-keygen` / spawn refusal /
|
||||
never-listening (the server's `-e` log tail carried in the reason) — never silently green.
|
||||
|
||||
**Findings**: no src/ changes needed — every observed issue was e2e-graph local
|
||||
(compile/fmt-level only). No bookings for the gate beyond the decisions above.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Completed 2026-10-30. The client-direction real-tool e2e landed as `tests/e2e_client.rs` (7 rows,
|
||||
fixture shape above): exec (exit-status parity, nonzero through real reaping), the direct-tcpip
|
||||
dial, the `-R` leg (port-0 mint + accepted arrival + data leg + cancel tearing the real listen
|
||||
down + unknown-cancel `ListenRefused`), and the three decline rows (sftp placeholder, host-key
|
||||
mismatch hard-decline with the real presented fingerprint on record, server-refused direct-tcpip
|
||||
with the connection staying usable). Verification: full `scripts/matrix.sh` run green — `cargo
|
||||
test` per build (none / git / session / tunnel / sftp / --all-features; the new binary compiles
|
||||
in every build and runs only its rows' builds: 2 / 2 / 3 / 5 / 2 / 7 rows), both clippy runs
|
||||
`-D warnings` clean, fmt clean, `cargo doc --no-deps` clean; plus 10 consecutive all-features
|
||||
e2e_client runs green (no flakes; per-row workdirs + the e2e-server's port allocator carried
|
||||
over). Skips are reasoned prints only; on this host sshd 9.6p1 is present, so every row ran.
|
||||
Reference in new issue
Block a user