docs(review): close the wave-3 review gate — verdict green (review-wave-3)

The wave-3 gate read the landed server mappings against
mapping.md/ADR-006/ADR-003/auth.md line by line: session/pty/shell/pipe
(translation bridge + the derivation contract rules 1-6), git exec
(full grammar, no-oracle validation, collapsed denial byte order),
route-1 bridge direct rows, the full -R listen flow + forwarded-tcpip
data leg, per-build decline matrices, identity observed at every seam,
bounded bookkeeping, and the uniform safe tracing vocabulary. All four
decomposition-time interpretations confirmed.

Fixed inline (this gate):
- install_forwarded_surface pre-checks the tunnel/forwarded op —
  alkcall's register silently replaces an existing entry, so a second
  adapter over the same shared seam registry silently stole the first
  adapter's arrival routes; now a failed construction
  (AdapterError::ListenRegistration), pinned by a new wire row
- git take drops a stored pty entry (combined-build stale state)
- doc hygiene: channel_cap release ordering, the session-row scoping
  of the handler Drop, the cancel-order recording, the post-cancel
  arrival caveat, the exit-chunk ADR lineage cross-ref, the stale
  lib.rs wave-state doc, the superseded dispatch test name, and
  mapping.md's listen-resource wording (address verbatim + tcp port)

Booked for wave 4: the git row's status-before-close honored by
scheduling not construction (needs a seam/shape change), the
channel-not-held wire test rows, the tty coverage minors (cancel path,
Closed/Break shape, stdout write deadline), and a defensive
ListenRouter token-collision pre-check.

Verified: cargo test (default) + --all-features (173 rows, 13
binaries), clippy --all-targets -D warnings ×2 (default +
--all-features), fmt --check, cargo doc --no-deps (0 warnings),
taskgraph validate (26 tasks).
This commit is contained in:
glm-5.3-flash committed 2026-10-29 05:22:14 +00:00
1 parent 3d0253d981
commit 930d9c1996
9 files changed
+316 -36

No files matched your search

+7 -3
View File
@@ -63,10 +63,14 @@ alktunnels 0.4.1's actual surfaces with POC-3 §C.4 as the template):
- **The listen dial** — family-ward through the consumer surface:
`TunnelListener::open(channel_client, TunnelParams {resource: <the
wire bind endpoint>, substrate: Tcp/Unix})`. The resource carries
the wire endpoint string verbatim — the OpenSSH client normalizes
wire bind endpoint>, substrate: Tcp/Unix})`. The resource is built
from the wire bind endpoint: the address string rides verbatim (the
OpenSSH client normalizes
the no-address case to `"localhost"` before it sends
(`channel_rfwd_bind_host` parity), so the door passes through; whose
(`channel_rfwd_bind_host` parity), so the door passes through), with
the tcp port appended (`host:port`; `0` stays `0` — the OS-picking
is the fabric's bind step, whose bound report feeds the out-param);
the unix path rides alone; whose
bind policy governs (wildcard vs loopback — the sshd `GatewayPorts`
posture) is the fabric's establisher/bind closure, assembly policy
at the family's provider. The dial is bounded (`LISTEN_DIAL_TIMEOUT`
+3 -2
View File
@@ -40,8 +40,9 @@
//! succeeds), the channel never establishes, and *no
//! `channel_close` can ever fire* — so the count must be released
//! from where the failure is known: inside the spawned bridge
//! task, immediately after the reject is answered. A success never
//! releases there (its close rides path 1).
//! task, **before** the reject is answered (the very next open
//! then observes the recovered budget — pinned by wire test). A
//! success never releases there (its close rides path 1).
//! 3. **The `-R` arrival pumps** (`w3-tunnel-listen`): a fabric
//! arrival is admitted into the owning route's count and opens the
//! SSH `forwarded-tcpip`/`forwarded-streamlocal` channel toward
+20 -10
View File
@@ -372,10 +372,14 @@ pub struct SessionHandler {
}
impl Drop for SessionHandler {
/// Fires the session rows' teardown signal (`w3-tty-session`):
/// every spawned serving task of this connection watches it and
/// Fires the teardown signal (`w3-tty-session`): every spawned
/// **session-row** serving task of this connection watches it and
/// cancels its alktty session (the kill-on-drop cleanup) instead
/// of outliving the connection. The `tunnel` build adds the `-R`
/// of outliving the connection. The git serving task does not
/// watch this signal — it ends through the channel duplex (stream
/// EOF / send failure) once the russh session dies, bounded by the
/// alkgit seam's own `session_wall_clock` (the alkgit limits the
/// assembly configured). The `tunnel` build adds the `-R`
/// leg's teardown (`w3-tunnel-listen`): the session's pending
/// listens' tokens leave the shared router (a fabric arrival after
/// the session is gone is the correlation-miss class —
@@ -1388,13 +1392,15 @@ async fn listen_request_dispatch(
/// variants (the client sends the same normalized string it sent
/// originally, and the *allocated* port for `port = 0` mints — the
/// value the listen reply carried); the path alone for the unix
/// variant. Order: the route leaves the shared router **before** the
/// entry leaves the session map (so a racing arrival is already the
/// correlation-miss class — no post-cancel half-serve), then the
/// listener count releases, then the family teardown spawns
/// (`TunnelListener::close` inside the spawn — a bounded local
/// shutdown + entry reap, not a serving path the hook may await).
/// `Ok(true)` iff a pending listen matched.
/// variant. Order: the entry leaves the session map and the route
/// leaves the shared router before any family teardown spawns (a
/// racing arrival that has not yet cloned its route is already the
/// correlation-miss class — no post-cancel half-serve; one that
/// cloned just before completes independently — the recorded
/// caveat), then the listener count releases, then the family
/// teardown spawns (`TunnelListener::close` inside the spawn — a
/// bounded local shutdown + entry reap, not a serving path the hook
/// may await). `Ok(true)` iff a pending listen matched.
#[cfg(feature = "tunnel")]
fn cancel_listen_dispatch(
handler: &mut SessionHandler,
@@ -1540,6 +1546,10 @@ fn git_row_dispatch(
let _ = session.channel_failure(channel);
return;
};
#[cfg(feature = "session")]
{
let _ = handler.ptys.remove(&channel);
}
let identity = handler.resolved_identity.clone();
let handle = session.handle();
serve::spawn_serving_path(git_map::serve_git_row(
+4 -4
View File
@@ -19,10 +19,10 @@
//! rest, decrypted at use (ADR-005), never env vars.
//!
//! Architecture: `docs/architecture/` (phase 1 — ADRs 001–006 accepted;
//! the dependency surface, feature graph, and wave-1 foundations are
//! landed; the server stack, the mappings, the client direction, and
//! validation are later implementation waves — wave 2 decomposes after
//! this gate). See also `docs/research/` and family ADR-003.
//! the foundations, the server stack, and the server-direction mappings
//! are landed through wave 3; the client direction, the validation
//! suite, and the release are later implementation waves). See also
//! `docs/research/`, `docs/plans/implementation.md`, and family ADR-003.
mod adapter;
mod channel_cap;
+2 -1
View File
@@ -132,7 +132,8 @@
//! 1–6 — normative)
//!
//! The alktty exit chunk (`{"type":"exit","code":i32}`,
//! exit-chunk-is-last per alktty's ADR-005 lineage) is the sole
//! exit-chunk-is-last per alktty's ADR-004 on the alknet ADR-055
//! lineage) is the sole
//! fidelity input, **never widened**: [`derive_exit`] maps it to
//! exactly one SSH exit report shape:
//!
+25 -5
View File
@@ -151,7 +151,12 @@
//! misses → teardown-at-birth), and `cancel_*` of an unknown
//! (address, bound-port) pair answers `false` — the vanilla
//! cancel contract (sshd parity: match by the raw wire string +
//! the bound port).
//! the bound port). One recorded caveat: an arrival that *cloned*
//! its route just before the cancel removes it still completes its
//! open + pump (the forwarded channel is independent of the
//! listener's teardown — the arrival is never half-open, but a
//! cancelled listen can deliver one already-accepted connection;
//! sshd parity).
//!
//! ## The runtime-Unix gate (OQ-11)
//!
@@ -393,10 +398,13 @@ impl Default for ListenRouter {
/// deployment policy; an assembly wanting a different per-identity
/// cap shapes it through its own `ServingConfig`/`registry`
/// composition upstream) — and spawns alktunnels' forward-op handler
/// over the crate's arrival pump. The registration is one-per-op-id-
/// per-registry (alkcall's rule): a conflicting registration is a
/// failed construction (fail-closed — never a route to a handler the
/// door does not own).
/// over the crate's arrival pump. The registration is
/// one-per-op-id-per-registry: alkcall's `register` silently
/// replaces an existing entry, so the door **pre-checks the op** —
/// a `tunnel/forwarded` registration that already exists (e.g. a
/// second adapter over the same shared registry) is a failed
/// construction (fail-closed — never a route to a handler the door
/// does not own).
///
/// On success the router rides back into the serve-config (the
/// session handlers read it) — `Ok` with the router installed, `Err`
@@ -419,6 +427,18 @@ pub(crate) fn install_forwarded_surface(serve: &mut config::ServeConfig) -> Resu
client.manager().clone(),
alkcall::channels::policy::default_policy(),
);
if seam
.registry
.registration(alktunnels::params::OP_TUNNEL_FORWARDED)
.is_some()
{
return Err(format!(
"the tunnel/forwarded op ({}) is already registered in the \
seam's registry — a conflicting registration would silently \
replace the door's arrival route",
alktunnels::params::OP_TUNNEL_FORWARDED
));
}
register_tunnel_forwarded_openable(
&core,
&seam.registry,
+210 -7
View File
@@ -1,7 +1,7 @@
---
id: review-wave-3
name: Wave 3 gate — the server-mappings review
status: pending
status: completed
depends_on: [w3-seam-config, w3-decline-tracing, w3-git-mapping, w3-tty-session, w3-tunnel-direct, w3-tunnel-listen]
scope: narrow
risk: low
@@ -68,15 +68,15 @@ booked (remediation before wave 4 decomposes).
## Acceptance Criteria
- [ ] Every ADR/mapping surface above read and confirmed (or
- [x] Every ADR/mapping surface above read and confirmed (or
corrected with the correction landed)
- [ ] The decline matrix verified per build through the harness;
- [x] The decline matrix verified per build through the harness;
the derivation contract verified against its rules; the
spawn-and-return constraint re-pinned over real serving paths
- [ ] 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 4 decomposition unblocked or findings
- [x] `taskgraph validate` clean
- [x] Verdict recorded; wave 4 decomposition unblocked or findings
booked
## References
@@ -89,4 +89,207 @@ booked (remediation before wave 4 decomposes).
## Notes
> To be filled at gate time.
### Gate reading (line by line, 2026-10-29; commits 270365e…3d0253d)
- **mapping.md line-by-line** ✓ — each spine row read against the
landed code: the session/pty/shell/pipe rows (translation bridge,
OQ-08 argv conventions, pipe-less shell serves pipe-mode), the git
exec row (full grammar, no-oracle validation, alkgit dispatch), the
direct-tcpip / direct-streamlocal rows (route-1 bridge), the
forwarded-tcpip row (echo args + bound port, teardown-at-birth on
correlation miss), the global listen rows (verbatim resource +
bound-port out-param — one doc correction landed: §The listen dial
now states the port appending, the code's `host:port` form), the
request-level table, and the derivation contract rules 1–6 in
`derive_exit` (incl. `i32::MIN` via `checked_abs` → 255,
`core_dumped` never, rule 3's table entry unreachable by
construction, the PTY-path rule-5 limit documented). The decline
matrix is green per feature build through the harness (per-build
cfg-pinned modules; unset-field rows — feature on, handle unset —
present in every featured build).
- **ADR-006** ✓ — route-1 bridge (accept only after the fabric open;
`ConnectFailed` on failure; the wave-2 stub retired into the real
decline), exec-only git (no subsystem dispatch anywhere in the
grammar; git service names decline), parse-only dispatch (no
detect residue), spawn-and-return re-pinned over the real serving
paths (the wave-2 mechanics rows still green; the inline listen
dial is the one recorded exception, bounded by
`LISTEN_DIAL_TIMEOUT` — wire-necessity reasoning documented).
- **ADR-003** ✓ — per-build matrices; honest advertisement
unchanged; the sftp feature still gates nothing and its rows
decline in every build (OQ-13); x11/auth-agent never-features
untouched; feature-to-dep isolation (`cargo tree` proven in
`w3-seam-config`).
- **Auth/identity** ✓ — the resolved identity observed at every seam:
alktty (the ownership witness row), alkgit (the authorize/ deny
row), tunnels (the CF-005/CF-006 establisher + ACL rows);
`set_identity`/`take_call_connection` appears **nowhere in src/**
(the detach decision recorded, the upstream ask booked — see below
for final disposition); the wave-2 `auth_succeeded` parked item
discharged as ride-along store; no username anywhere (the
safety-scan row).
- **OQ resolutions in code** ✓ — OQ-08 (unset-declines, both field
classes, `wrapper ++ [cmd]` verbatim-append), OQ-09 (env declined
unconditionally), OQ-10 (derivation rules + PTY-path limit
documented), OQ-11 (runtime-Unix gates compile-everywhere with
dial-call-witness-at-zero off-Unix rows), OQ-13 (sftp rows
unchanged in every build).
- **Bounded resources** ✓ — the cap across the fabric window (admit
at the hook, release-before-reject on fabric failure, disjoint
saturating release sites verified per row), the listener
bookkeeping bounded by a dedicated `max_concurrent_channels`-ceiling
counter, the route map bounded by construction (minted only at
accepted listens, removed at cancels + session teardown — the
`Drop` really removes from the shared router), the control-row
surfaces bounded (`try_send`, never awaited on the packet loop),
the bridge adapters bounded (mpsc 64, 64 KiB duplexes, 16 KiB read
buffers, `MAX_CHUNK_LEN` frame gates). No unbounded shape found in
any serving path.
- **Tracing** ✓ — the uniform event vocabulary at every
decline/serve site (row + feature_build + channel_id + class +
reason + exec_route; declines `debug`, the one `warn` the
serving-failure arm), safety posture pinned by scan (no username,
no fingerprint, no secret ever in an event).
- **The smokes** ✓ — git clone 2.43 / `ssh -L` + curl / `ssh -tt`
pty / `ssh -R` + curl: all four landed and green in this
environment; every one carries a check-gated skip-with-reason
posture, nothing silently green.
- **Wave-2 booked items** ✓ — decline tracing landed
(`w3-decline-tracing`); the acceptor vocabulary landed
(`w3-tunnel-listen`: harness accept hook + per-arrival cap); the
deferred identity-landing assertion discharged (each seam rides the
resolved identity, wire-witnessed); the inherited
`auth-agent`/`forwarded-streamlocal`-open watch item unchanged (no
pin touch this wave).
- **Docs honesty** ✓ — each replaced stub's module docs name what it
now is and what remains wave-4/5; the `set_identity` reading, the
resource-naming convention, the inline-dial bound, and
portable-pty's PTY-path exit shape are all recorded in module docs
(one overbroad Drop doc corrected inline, below).
### Interpretations (flagged at decomposition) — all confirmed
1. **Whole-`Option` struct per seam** (vs flat `Option` fields) —
confirmed: each seam is consumed atomically by exactly one seam
call; the flat single-field tunnel handle stays flat. Recorded in
`w3-seam-config`.
2. **The server-side sftp bullet already discharged in wave 2** —
confirmed: the rows are in `tests/dispatch_core.rs` per build.
3. **The `-R` listen flow's biggest open closed without a fork** —
confirmed: the topology closed over the published alkcall 0.10.1 /
alktunnels 0.4.1 surfaces via the `TunnelListenSeam`
course-correction; a scratch probe (published crates only) proved
the flow before landing; nothing forked or absorbed.
4. **The wave-2 booked items' wave-3 homes** — confirmed as above.
### Minor issues found and fixed inline (this session)
Source/doc fixes (all commit-tested; suite re-run green after):
- **Duplicate `tunnel/forwarded` registration now fails
construction** (the gate's one real fix): alkcall's
`OperationRegistry::register` silently *replaces* an existing op
entry, contradicting the `install_forwarded_surface` docs' recorded
fail-closed claim — a second adapter over the same shared seam
registry would silently steal the first adapter's arrival routes.
`install_forwarded_surface` now pre-checks the op
(`registry.registration(OP_TUNNEL_FORWARDED)`) and refuses with
`AdapterError::ListenRegistration`; new wire-level row
`a_second_adapter_over_a_shared_listen_registry_fails_construction`
pins both constructs/refuse.
- **channel_cap.rs** — the bridge-failure release doc said "after the
reject is answered"; the code (and the pinned test) release
*before* the reject. Doc corrected.
- **handler.rs** — the `Drop` doc claimed "every spawned serving task
watches" the teardown signal; scoping corrected (the session rows
watch; the git task ends through the duplex, bounded by alkgit's
`session_wall_clock`). The cancel-form doc's recorded ordering
(router-before-map) was inverted vs the code; corrected, with the
post-cancel-race caveat recorded.
- **tunnel_map.rs** — the "never half-serves" bookkeeping claim now
records the one-arrival caveat: an arrival that cloned its route
just before a cancel completes independently (never half-open;
sshd parity).
- **tty_map.rs** — stale ADR cross-ref on the exit chunk (alktty
ADR-005 → ADR-004 on the alknet ADR-055 lineage).
- **lib.rs** — the crate-level wave-state doc still said "wave 2
decomposes after this gate"; updated to the landed state.
- **tests/dispatch_core.rs** — the stale
`unknown_git_services_route_to_the_pipe_row` name/doc superseded by
the w3 decision ("off the pipe row"); renamed, verdicts preserved
(the wire shape coincides — why it never failed).
- **handler.rs (git row)** — a pty-then-git-exec in a combined build
left the stored pty entry until close; the git take now drops it
(the pipe row's consumption shape).
- **mapping.md** — the §listen-dial resource wording corrected to the
code's assembled form (address verbatim + tcp port appended;
`0` stays `0`).
### Booked findings (not remediation this gate — wave-4 material)
1. **The git row's status-before-close is honored by scheduling, not
by construction** (the gate's only structural moderate):
`serve_duplex_resolved` splits the channel stream internally and
its session halves drop when the serve returns — russh's
`ChannelCloseOnDrop` rx-half emits a server→client
`CHANNEL_CLOSE` *inside* the seam call, before
`serve_git_row`'s explicit `exit_status_request`. Today the
ordering holds (the task's continuation queues the report in the
same poll, ahead of the drop's send) and every wire row passes,
but a full `Sender<Msg>` buffer at the serve tail could order the
implicit close first and silently drop the report (russh no-ops
`exit_status_request` for an already-closed channel). A fix wants
a seam/shape change (split halves into the seam, or queue the
report while the stream is alive) — beyond this gate's inline
budget; book a wave-4 hardening item. (The tty rows are NOT in
this class: their report precedes any close-contracting drop in
one task.)
2. **The `channel-not-held` guard lacks wire test rows** — a
documented decline class on all three rows (git/tty pipe/shell),
constructible on the wire (a second exec on a served channel),
but no row asserts it in any build; mapping.md's every-row
tested-in-every-build convention names it contract territory.
Test-only task; book for wave 4's decomposition.
3. **Tty coverage gaps** (minors, one ticket's worth): the
`channel_close`-fired per-channel cancel path is unexercised on
the wire (only the teardown signal is); the Closed/Break
no-exit-chunk close shape has no wire row; the tty stdout
`write_all` carries no deadline (backpressure bounded, liveness
covered by inactivity timeout — record as a known limit only).
4. **Defensive `ListenRouter` token-collision pre-check** (minor):
`register` silently replaces on token collision; safety rests on
the fabric's ADR-008 mint discipline. A fail-closed
decline-the-listen-on-collision is a cheap wave-4 addition.
5. **Upstream asks to file** (booked with their owners, not this
crate): the alktunnels/alkcall "non-detaching post-construction
identity seam" note (`w3-tunnel-direct`'s recorded decision — the
door keeps the no-detach posture until upstream proposes a seam),
and mapping.md's recorded event-vocabulary nuance for the
unreachable mismatch arms (`correlation-miss` naming).
No blocking issues; no code shape errors found. Wave 4 decomposition
is unblocked and should absorb items 1–4 above.
### Verification (all green, 2026-10-29)
`cargo test` (default build) · `cargo test --all-features` (173 rows
across 13 binaries) · `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` ✓ (26 tasks).
## Summary
**Verdict: green.** The wave-3 server mappings read clean against
mapping.md/ADR-006/ADR-003/auth.md line by line: the translation
bridge + derivation contract, the exec-only git grammar with the
no-oracle dispatch and the byte-pinned collapsed denial, the route-1
bridge and the full `-R` listen flow closed over the published
surfaces, per-build decline matrices, identity observed at every
seam, bounded bookkeeping throughout, and a uniform safe tracing
vocabulary. All four flagged interpretations confirmed; one real
fail-closed hole fixed inline (duplicate listen registration) plus
eight doc/test-hygiene minors; four findings booked for wave 4 (the
git exit-report close race, the `channel-not-held` wire rows, the
tty coverage minors, the router token-collision pre-check). Wave 4
decomposition is unblocked.
+5 -4
View File
@@ -284,11 +284,12 @@ mod git_build {
}
/// - *Contract stamp:* POC-3 §2 (unknown git services take the
/// honest decline-with-reason surface — `w3-git-mapping`'s
/// decided class, off the pipe row too; the reply vocabulary is
/// shared with parse-then-fail: failure, channel alive).
/// agreed declined surface — `w3-git-mapping`'s decided class,
/// off the pipe row: `ExecRoute::Declined`, build-independent;
/// the reply vocabulary is shared with parse-then-fail: failure,
/// channel alive).
#[tokio::test]
async fn unknown_git_services_route_to_the_pipe_row() {
async fn unknown_git_services_take_the_declined_surface() {
let session = authenticated().await;
for command in ["git-send-pack '/r'", "git-upload-archive '/r'"] {
let mut channel = open_session_channel(&session.client)
+40
View File
@@ -1696,6 +1696,46 @@ mod serving {
session.unmount().await;
}
/// - *Contract stamp:* the door-side registration is
/// one-per-op-per-registry (mapping.md §Global-request rows / the
/// `install_forwarded_surface` claim): alkcall's `register`
/// silently replaces an existing op entry, so the door
/// pre-checks — a second `SshAdapter` composed over the same
/// shared seam registry is a **failed construction**
/// (`AdapterError::ListenRegistration`), never a silent steal of
/// the first adapter's arrival routes.
#[tokio::test]
async fn a_second_adapter_over_a_shared_listen_registry_fails_construction() {
let double = wire_fabric_with_listen(true, true).await;
let provider = Arc::new(MemIdentityProvider::new());
provider.register(
fixture("alpha").fingerprint,
identity("tunnel-rider", &["ssh"]),
);
let mut first = harness_serve_config(
Arc::clone(&provider) as Arc<dyn alkcall::core::auth::IdentityProvider>,
&[fixture("bravo")],
Limits::default(),
);
first.channel_client = Some(Arc::clone(&double.client));
first.tunnel_listen_seam = Some(TunnelListenSeam::new(Arc::clone(&double.registry)));
let _first = SshAdapter::new(first)
.await
.expect("the first adapter over the shared registry constructs");
let mut second = harness_serve_config(provider, &[fixture("charlie")], Limits::default());
second.channel_client = Some(Arc::clone(&double.client));
second.tunnel_listen_seam = Some(TunnelListenSeam::new(Arc::clone(&double.registry)));
let refused = SshAdapter::new(second)
.await
.expect_err("a conflicting registration is a failed construction");
assert!(
matches!(refused, alkssh::AdapterError::ListenRegistration(_)),
"the refusal is the ListenRegistration class, got {refused:?}"
);
}
}
#[cfg(all(feature = "tunnel", unix))]