docs(review): close the wave-4 review gate — verdict green (review-wave-4)
- Gate reading recorded line by line: client.md (dial surface, op rows, acceptor, lifecycle primitives), ADR-003 symmetry, ADR-005/ OQ-05/OQ-07, bounded resources, tracing, smokes, docs honesty — all confirmed - Wave-3 gate booked items 1-4 verified discharged; item 5 verified still booked with its owners (nothing absorbed) - Inline fix: the accepted-open handoff counter now releases on completion or unwind (HandoffCapGuard panic-safety; a panicking assembly acceptor can no longer strand a held slot) + unit row - Inline fix: lib.rs crate-level wave-state doc sentence (stale over w4-lifecycle) - w4-reverse-listen / w4-lifecycle Summary placeholder lines filled Verification: cargo test (default / --all-features / --features tunnel) all green; clippy x2 -D warnings clean; cargo fmt --check clean; cargo doc --no-deps 0 warnings; taskgraph validate (35 tasks)
This commit is contained in:
1 parent
dec644e653
commit
671a779ce3
6 files changed
+272
-26
No files matched your search
+48
-10
@@ -76,8 +76,10 @@
|
||||
//! set the registry would have to serve). The per-connection
|
||||
//! **accepted-open handoff count** is the second dedicated counter
|
||||
//! against the same ceiling (admitted in the dial handler's open
|
||||
//! hook, accepted-with-the-count-held, released when the acceptor's
|
||||
//! `accept` call completes — no accepted-open ledger anywhere
|
||||
//! hook, accepted-with-the-count-held, released when the handoff
|
||||
//! task ends — the acceptor's `accept` completing *or the task
|
||||
//! unwinding* ([`HandoffCapGuard`]: a panicking assembly acceptor
|
||||
//! can never strand a held slot) — no accepted-open ledger anywhere
|
||||
//! else: the pump is the acceptor's from the handoff on, the
|
||||
//! channel's transport bounds are russh's windows, and the slot read
|
||||
//! is the arrival admission).
|
||||
@@ -217,9 +219,11 @@ impl std::fmt::Debug for ForwardedStreamlocal {
|
||||
/// The `forwarded-tcpip` acceptor — the registry's per-type slot
|
||||
/// trait. `accept` runs on the spawned handoff task (never the
|
||||
/// packet loop): the assembly's pump/home of the open lives inside
|
||||
/// it; the crate releases its handoff counter when the call returns,
|
||||
/// so the family shape (hand off to a queue, return) keeps the
|
||||
/// counter's meaning "open accepted, handoff in flight".
|
||||
/// it; the crate releases its handoff counter when the handoff task
|
||||
/// ends — the call returning *or the task unwinding*
|
||||
/// ([`HandoffCapGuard`]) — so the family shape (hand off to a queue,
|
||||
/// return) keeps the counter's meaning "open accepted, handoff in
|
||||
/// flight".
|
||||
#[async_trait]
|
||||
pub trait TcpipForwardedAcceptor: Send + Sync {
|
||||
/// Serves one accepted open. Never invoked for an unregistered
|
||||
@@ -341,13 +345,28 @@ impl std::fmt::Debug for AcceptorRegistry {
|
||||
// The server-initiated opens' handoff (the dial handler's routed paths)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// The handoff counter's panic-safe release — the accepted open's count
|
||||
/// releases exactly at the handoff task's end, on *completion or
|
||||
/// unwind*: a panicking assembly acceptor (or any panic in the handoff
|
||||
/// body) can never strand a held slot past the task. Saturating under
|
||||
/// the [`ChannelCap`] (never manufactures capacity).
|
||||
struct HandoffCapGuard(Arc<ChannelCap>);
|
||||
|
||||
impl Drop for HandoffCapGuard {
|
||||
fn drop(&mut self) {
|
||||
self.0.release();
|
||||
}
|
||||
}
|
||||
|
||||
/// The accepted `forwarded-tcpip` open's handoff task — the
|
||||
/// spawn-and-return rule's client mirror (ADR-006 decision 4; the
|
||||
/// hook runs in the packet loop and returns fast): accepts the open on
|
||||
/// the wire, converts the channel to the family duplex, delivers the
|
||||
/// payload to the assembly's acceptor, and releases the handoff
|
||||
/// counter when the acceptor's call completes (the recorded release
|
||||
/// site — the count's meaning is "accepted, handoff in flight").
|
||||
/// counter when the handoff task ends — the acceptor's `accept`
|
||||
/// completing *or the task unwinding* ([`HandoffCapGuard`]; the
|
||||
/// recorded release site — the count's meaning is "accepted, handoff
|
||||
/// in flight").
|
||||
#[cfg_attr(feature = "tunnel", allow(clippy::too_many_arguments))]
|
||||
pub(crate) async fn handoff_forwarded_tcpip(
|
||||
acceptor: Arc<dyn TcpipForwardedAcceptor>,
|
||||
@@ -371,8 +390,9 @@ pub(crate) async fn handoff_forwarded_tcpip(
|
||||
stream: channel.into_stream(),
|
||||
},
|
||||
};
|
||||
let cap_guard = HandoffCapGuard(open_cap);
|
||||
acceptor.accept(open).await;
|
||||
open_cap.release();
|
||||
drop(cap_guard);
|
||||
observe::serving_path_ended("forwarded-tcpip", channel_number, None);
|
||||
}
|
||||
|
||||
@@ -394,8 +414,9 @@ pub(crate) async fn handoff_forwarded_streamlocal(
|
||||
stream: channel.into_stream(),
|
||||
},
|
||||
};
|
||||
let cap_guard = HandoffCapGuard(open_cap);
|
||||
acceptor.accept(open).await;
|
||||
open_cap.release();
|
||||
drop(cap_guard);
|
||||
observe::serving_path_ended("forwarded-streamlocal", channel_number, None);
|
||||
}
|
||||
|
||||
@@ -666,7 +687,7 @@ impl SshConnection {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::AcceptorHeld;
|
||||
use super::{AcceptorHeld, HandoffCapGuard};
|
||||
use crate::client_accept::{
|
||||
AcceptorRegistry, ForwardedStreamlocal, ForwardedTcpip, StreamlocalForwardedAcceptor,
|
||||
TcpipForwardedAcceptor,
|
||||
@@ -766,4 +787,21 @@ mod tests {
|
||||
"an acceptor is already registered for this channel type"
|
||||
);
|
||||
}
|
||||
|
||||
/// - *Contract stamp:* the handoff counter's panic-safe release
|
||||
/// (the bounded-bookkeeping cap relation) — the
|
||||
/// [`HandoffCapGuard`] releases on unwind, so a panicking
|
||||
/// assembly acceptor can never strand a held slot past the
|
||||
/// handoff task.
|
||||
#[test]
|
||||
fn the_handoff_guard_releases_on_unwind() {
|
||||
let cap = Arc::new(crate::channel_cap::ChannelCap::default());
|
||||
assert!(cap.admit(1));
|
||||
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
let _guard = HandoffCapGuard(Arc::clone(&cap));
|
||||
panic!("the assembly acceptor panics");
|
||||
}));
|
||||
assert!(outcome.is_err(), "the panic rode through");
|
||||
assert_eq!(cap.active(), 0, "the held slot released on unwind");
|
||||
}
|
||||
}
|
||||
@@ -47,8 +47,10 @@
|
||||
//! [`crate::client_accept`]): a dedicated per-connection counter —
|
||||
//! sharing the dial's `Limits::max_concurrent_channels` ceiling the
|
||||
//! server direction's per-session cap uses — admitted in the hook
|
||||
//! before the accept, released when the acceptor's call completes in
|
||||
//! the spawned task; a full counter declines the arrival cleanly
|
||||
//! before the accept, released when the handoff task ends (the
|
||||
//! acceptor's call completing *or the task unwinding* —
|
||||
//! [`crate::client_accept`]'s `HandoffCapGuard` panic-safety); a full
|
||||
//! counter declines the arrival cleanly
|
||||
//! (`cap-exceeded`).
|
||||
|
||||
#[cfg(feature = "tunnel")]
|
||||
@@ -76,7 +78,8 @@ use crate::{DialError, fingerprint};
|
||||
/// `w4-reverse-listen` surface, under `tunnel`): the acceptor registry
|
||||
/// the two forwarded hooks route through, plus the accepted-open
|
||||
/// handoff counter and its ceiling (the dial's
|
||||
/// `Limits::max_concurrent_channels`).
|
||||
/// `Limits::max_concurrent_channels`; released when the handoff task
|
||||
/// ends — completion or unwind, `HandoffCapGuard`'s panic-safety).
|
||||
#[cfg(feature = "tunnel")]
|
||||
pub(crate) struct TunnelSurface {
|
||||
acceptors: Arc<AcceptorRegistry>,
|
||||
|
||||
+3
-3
@@ -20,9 +20,9 @@
|
||||
//!
|
||||
//! Architecture: `docs/architecture/` (phase 1 — ADRs 001–006 accepted;
|
||||
//! the foundations, the server stack, the server-direction mappings, and
|
||||
//! the client dial + op rows + the `-R` acceptor leg are landed through
|
||||
//! wave 4; the lifecycle primitives, the validation suite, and the
|
||||
//! release are later implementation waves). See also `docs/research/`,
|
||||
//! the client direction — dial, op rows, the `-R` acceptor leg, and the
|
||||
//! lifecycle primitives — are landed through wave 4; the validation
|
||||
//! suite and the release are wave 5). See also `docs/research/`,
|
||||
//! `docs/plans/implementation.md`, and family ADR-003.
|
||||
|
||||
mod adapter;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: review-wave-4
|
||||
name: Wave 4 gate — the client-direction review
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [w4-dial, w4-op-rows, w4-reverse-listen, w4-lifecycle, w4-git-exit-close, w4-channel-not-held-rows, w4-tty-coverage, w4-router-collision]
|
||||
scope: narrow
|
||||
risk: low
|
||||
@@ -64,16 +64,16 @@ booked (remediation before wave 5 decomposes).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Every client.md/ADR surface above read and confirmed (or
|
||||
- [x] Every client.md/ADR surface above read and confirmed (or
|
||||
corrected with the correction landed)
|
||||
- [ ] The client-side per-build matrices verified through the server
|
||||
- [x] The client-side per-build matrices verified through the server
|
||||
double; the acceptor contract verified (registered/unregistered/
|
||||
unfeatured/late-install); the wave-3 booked items 1–4 verified
|
||||
discharged
|
||||
- [ ] Full verification set green (`cargo test`, `--all-features`,
|
||||
- [x] Full verification set green (`cargo test`, `--all-features`,
|
||||
clippy ×2 `-D warnings`, fmt, `cargo doc --no-deps`)
|
||||
- [ ] `taskgraph validate` clean
|
||||
- [ ] Verdict recorded; wave 5 decomposition unblocked or findings
|
||||
- [x] `taskgraph validate` clean
|
||||
- [x] Verdict recorded; wave 5 decomposition unblocked or findings
|
||||
booked
|
||||
|
||||
## References
|
||||
@@ -89,8 +89,192 @@ booked (remediation before wave 5 decomposes).
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
### Gate reading (line by line, 2026-10-29; commits 9cf5bfb…dec644e)
|
||||
|
||||
Commits verified against the decomposition: all eight tasks' hashes
|
||||
match `docs/plans/implementation.md`'s decomposition record; every
|
||||
task file carries its completion records and checked acceptance
|
||||
criteria.
|
||||
|
||||
- **client.md line-by-line** ✓ — read against the landed code:
|
||||
§The dial surface (`client.rs` — the four-step fail-closed
|
||||
sequence: decrypt-at-dial key load, the bounded russh `Config`
|
||||
with the keepalive 15 s / 3 posture and the always-set wall clock,
|
||||
the policy at `check_server_key`, the single publickey-only auth;
|
||||
the sanctioned `username` `DialConfig` amendment recorded honestly
|
||||
— a required parameter, no crate default, never identity, never
|
||||
logged); §Op rows (`client_ops.rs` — every table row present: the
|
||||
exec/pty/shell rows under `session`, the direct rows under
|
||||
`tunnel`, the git exec row under `git` over the shared grammar's
|
||||
construction arm, the sftp placeholder in every build; POC-3
|
||||
§D.3 mechanics pinned in code + rows — `exec()` not
|
||||
`request_exec`, the `wait()`-drain Success/Failure, split-halves
|
||||
wait-pumps for the exit-consuming rows and straight
|
||||
`into_stream` for the exit-less, the fire-and-forget controls
|
||||
sent from the live pump, no queue consumption before any
|
||||
conversion); §The acceptor (`client_accept.rs` + the
|
||||
`client_handler.rs` hooks — per-type fixed slots, refuse-never-
|
||||
replace, arrival-time reads, decline-not-buffer, late-install
|
||||
over the live connection, listen rows gated pre-wire, the two
|
||||
dedicated counters against the one ceiling); §Lifecycle
|
||||
primitives (`client_accept.rs` handles + `client.rs` §Lifecycle
|
||||
posture — explicit cancels, `Disconnect::ByApplication` the only
|
||||
clean path, drop-is-never-the-clean-path row-pinned both ways,
|
||||
the no-reconnect/restore-policy boundary stated in module docs;
|
||||
the crate owns no policy). client.md's landing blocks (acceptor/
|
||||
lifecycle/op-row shapes recorded at landing) are in the doc.
|
||||
- **ADR-003 symmetry** ✓ — the features gate both directions
|
||||
(`Cargo.toml` unchanged: `session`/`git`/`tunnel`/`sftp`,
|
||||
`default = []`); the client exports ride the same gates
|
||||
(`RemoteSession` under `session`, `TunnelChannel` + the acceptor
|
||||
surface + `ReverseListener` under `tunnel`, `GitPackSession`
|
||||
under `git`, the sftp row feature-free); the per-build matrices
|
||||
are green (the default build's 16 binaries + per-feature/
|
||||
`--all-features`; the unfeatured builds' fail-closed wire rows
|
||||
ride `tests/client_dial.rs`'s decline-all row — the
|
||||
`client_handler.rs` hooks are cfg-declined in every build);
|
||||
honest advertisement unchanged; x11/agent never-features
|
||||
untouched on both directions.
|
||||
- **ADR-005 / OQ-05 / OQ-07** ✓ — decrypt-at-dial with every
|
||||
`KeySourceError` posture a no-dial outcome (`DialError::KeySource`
|
||||
preserved per-variant; `error.rs` taxonomy rows); the policy seam
|
||||
consumed at the hook (`client_handler.rs::check_server_key` — the
|
||||
fingerprint rides the crate's single path, `PresentedHostKey`
|
||||
carries host/port, the verdict passes through; `RejectAll`
|
||||
connects to nothing, no accept-all built-in); the wave-1
|
||||
`Zeroizing` wrap posture intact (`key_source.rs`, untouched).
|
||||
- **The wave-3 gate's booked items 1–4** ✓ — all discharged:
|
||||
item 1 (`w4-git-exit-close`) — the split-halves seam duplex
|
||||
(`ChannelHalveReader` over the owned close-free read half; no
|
||||
drop path ever messages the wire) with the by-construction
|
||||
property wire-pinned and the row falsifying the old shape
|
||||
deterministic-red-under-revert; item 2
|
||||
(`w4-channel-not-held-rows`) — the guard's wire rows on all
|
||||
three served rows per build, vocabulary-asserting; item 3
|
||||
(`w4-tty-coverage`) — the `channel_close`-fired cancel path
|
||||
wire-witnessed, the Closed/Break no-exit-chunk shape row-pinned
|
||||
(Break's frame classification unit-rowed, wire-unreachable,
|
||||
recorded), the `write_all` no-deadline limit recorded in module
|
||||
docs; item 4 (`w4-router-collision`) — the register-refuses
|
||||
pre-check with the error-surface decision recorded honestly (the
|
||||
wire-time decline disposition, not a taxonomy variant that would
|
||||
kill the session). **Item 5 verified still booked with its
|
||||
owners, not absorbed**: no `set_identity`/`take_call_connection`
|
||||
anywhere in `src/` code (doc references only, recording the
|
||||
no-detach posture + the upstream ask), and mapping.md's
|
||||
correlation-miss event-vocabulary nuance records stand.
|
||||
- **Bounded resources** ✓ (convention 9 read over every new
|
||||
client serving/pumping path) — the acceptor registry bounded by
|
||||
construction (two slots); the reverse-listen count and the
|
||||
accepted-open handoff count are two dedicated `ChannelCap`
|
||||
counters against the same `Limits::max_concurrent_channels`
|
||||
ceiling (admit pre-wire/arrival, release at confirmed cancels /
|
||||
refused paths / the handoff task's end); the pumps bounded
|
||||
(64 KiB duplexes, the 16 KiB git pump buffer, the 1024-message
|
||||
launch-drain cap, russh windows verbatim, the always-on wall
|
||||
clock); the git row's command/repo gates answer pre-wire. One
|
||||
gap found and fixed inline (below).
|
||||
- **Tracing** ✓ — the client-side decline paths ride the uniform
|
||||
vocabulary (`decline_open` with `no-acceptor` / `cap-exceeded` /
|
||||
`never-feature`; the skeleton's decline rows event-pinned); the
|
||||
safety posture held — structurally no username/fingerprint/secret
|
||||
parameter exists on any event helper (the `&'static str`
|
||||
vocabulary); the client op rows' typed surfaces carry outcomes
|
||||
without events (the recorded asymmetry decision).
|
||||
- **The smokes** ✓ — three recorded honestly: the alkssh-client ↔
|
||||
alkssh-server dial smoke (`tests/client_dial.rs`), the client-exec
|
||||
↔ server-session-rows smoke (`tests/client_ops.rs`, check-gated
|
||||
on `sh`), the full-circle reverse-listen smoke
|
||||
(`tests/tunnel_mapping.rs`); real-`sshd` e2e named wave-5
|
||||
territory explicitly in each task's records — nothing silently
|
||||
green, nothing dropped.
|
||||
- **Docs honesty** ✓ — module docs name each new surface and its
|
||||
remaining wave-5 material (the fake-`sshd` posture, the
|
||||
DialConfig amendment, the russh client hook shapes at this pin,
|
||||
the acceptor-registry shape decision, the recorded wire facts —
|
||||
the port-0-only mint, the drop/is-closed semantics); one stale
|
||||
crate-level sentence fixed inline (below).
|
||||
|
||||
### Minor issues found and fixed inline (this session)
|
||||
|
||||
- **The accepted-open handoff counter's panic-unsafe release** (the
|
||||
gate's one code fix): the counter released only after
|
||||
`acceptor.accept(...)` returned — an assembly acceptor panicking
|
||||
inside `accept` stranded one held slot for the connection's
|
||||
lifetime (a bounded-resource leak path on the new cap). Fixed
|
||||
with a panic-safe guard (`HandoffCapGuard` in
|
||||
`src/client_accept.rs`): the release fires at the handoff task's
|
||||
end, on completion *or unwind*; the recorded release-site wording
|
||||
updated in the module docs, the trait docs, and
|
||||
`client_handler.rs`'s two references; a unit row
|
||||
(`the_handoff_guard_releases_on_unwind`) pins the unwind release.
|
||||
No surface change, no behavior change on any happy path.
|
||||
- **`lib.rs` crate-level wave-state doc** still said the lifecycle
|
||||
primitives were "later implementation waves" (stale over
|
||||
`w4-lifecycle`; the same staleness class the wave-3 gate fixed
|
||||
inline). Corrected to the landed state.
|
||||
|
||||
### Interpretations (flagged at decomposition) — all confirmed
|
||||
|
||||
1. **The fail-closed client Handler skeleton in `w4-dial`, the
|
||||
registry in `w4-reverse-listen`** — confirmed: the skeleton's
|
||||
decline-all default is row-pinned in every build, and the
|
||||
registry grows exactly the two forwarded hooks; the split kept
|
||||
both surfaces reviewable.
|
||||
2. **The fake-`sshd` client-direction vehicle in `tests/common`** —
|
||||
confirmed: vanilla-parity, real loopback TCP, one dial per
|
||||
instance, and the harness's `ForwardedAcceptor` vocabulary was
|
||||
grown (not forked) into `client_accept.rs`'s real surface.
|
||||
3. **No `DialConfig` course-correction anticipated** — confirmed,
|
||||
with the one sanctioned exception recorded in-task (the required
|
||||
`username` — the USERAUTH_REQUEST's structural requirement; the
|
||||
amendment follows the `w3-seam-config` pattern and is honestly
|
||||
documented).
|
||||
4. **The hardening tasks ordered by single-writer needs** —
|
||||
confirmed: `tests/git_mapping.rs` then `tests/tty_mapping.rs`
|
||||
sequencing held, no cross-task file conflicts in the landed
|
||||
history.
|
||||
|
||||
### Verification (all green, 2026-10-29)
|
||||
|
||||
`cargo test` (default build) · `cargo test --all-features` (all 16
|
||||
binaries green) · `cargo test --features tunnel` (the gate's
|
||||
per-feature spot re-run, covering the edited acceptor surface + the
|
||||
new guard row) · `cargo clippy --all-targets -- -D warnings` ✓ ·
|
||||
`cargo clippy --all-features --all-targets -- -D warnings` ✓ ·
|
||||
`cargo fmt --check` ✓ · `cargo doc --no-deps` 0 warnings ·
|
||||
`taskgraph validate` ✓ (35 tasks).
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
**Verdict: green.** The client direction reads clean against
|
||||
client.md/ADR-003/ADR-005 line by line: the four-step fail-closed
|
||||
dial over the bounded config (the sanctioned `username` amendment
|
||||
recorded), the op rows with the POC-3 mechanics pinned in code
|
||||
(split-halves wait-pumps vs straight conversions; the typed-open
|
||||
decline mirror family-typed; the sftp placeholder in every build),
|
||||
the acceptor registry as the refuse-never-replace per-type-slot
|
||||
gate with arrival-time declines and bounded two-counter bookkeeping,
|
||||
and the lifecycle primitives with the drop/clean-close boundary
|
||||
row-pinned both ways and the no-policy posture stated. All three
|
||||
interpretations confirmed except as recorded (all favorable); the
|
||||
wave-3 booked items 1–4 verified discharged and item 5 verified
|
||||
still booked upstream — nothing absorbed. The full verification set
|
||||
is green. Two minors fixed inline (the handoff counter's
|
||||
panic-unsafe release — the one code fix, guard + unit row; a stale
|
||||
crate-level wave-state doc sentence). No structural findings; wave
|
||||
5 decomposition is unblocked and should absorb nothing beyond its
|
||||
own plan (the decline matrix, real-tool e2e, fuzzing, docs, the
|
||||
publish).
|
||||
|
||||
## Summary
|
||||
|
||||
**Verdict: green** (2026-10-29) — see Notes for the full gate
|
||||
reading. All eight wave-4 tasks verified against the client.md/ADR
|
||||
contract surfaces line by line; the wave-3 gate's booked items 1–4
|
||||
discharged, item 5 verified still booked upstream; the full
|
||||
verification set + `taskgraph validate` green. Two inline fixes
|
||||
landed with the gate: the accepted-open handoff counter's
|
||||
panic-safe release (`HandoffCapGuard` — the gate's one code fix)
|
||||
and the stale crate-level wave-state doc sentence in `lib.rs`.
|
||||
Wave 5 decomposition is unblocked.
|
||||
@@ -165,7 +165,17 @@ remain under `--all-features`, unchanged).
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
The OQ-12 primitives landed: the `ReverseListener` handles carrying
|
||||
the actually-bound endpoint with the explicit wire-honest `cancel()`
|
||||
(releases the listener count exactly once per confirmed cancel; the
|
||||
stateless cancel forms compose into the same shared paths), the
|
||||
`SshConnection` internals restructured behind the arc so handles
|
||||
cancel against a live stack independently, the public surface
|
||||
unchanged, the abrupt-drop/clean-close boundary row-pinned both ways
|
||||
(drop is never the clean path; `close()` is), and the
|
||||
primitives-not-policy posture stated in the module docs and
|
||||
client.md's landing block. No reconnect/restore policy in the crate.
|
||||
Details in the `Landed` block below.
|
||||
|
||||
Landed (`feat(client)`: w4-lifecycle):
|
||||
|
||||
|
||||
@@ -158,7 +158,18 @@ aborts explicitly now).
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
The `-R` leg landed complete: the forward-request rows
|
||||
(`tcpip_forward`/`streamlocal_forward` + the cancel forms, the
|
||||
runtime-Unix gate on the listen side, the port-0-only mint fact
|
||||
surfaced), the acceptor registry as the real crate surface
|
||||
(per-type fixed slots, refuse-never-replace, arrival-time reads,
|
||||
decline-not-buffer, late-install), the forwarded hooks routed
|
||||
through it with bounded two-counter bookkeeping, the data leg
|
||||
handed to the assembly acceptor on spawned handoff tasks, and the
|
||||
per-build contract rows through the fake-`sshd`'s real-socket `-R`
|
||||
server half plus the full-circle smoke through the server
|
||||
direction's fabric. Real-`sshd` `-R` stays wave-5 e2e, recorded.
|
||||
Details in the `Landed` block below.
|
||||
|
||||
Landed (`feat(client)`: w4-reverse-listen):
|
||||
|
||||
|
||||
Reference in new issue
Block a user