# Rust fresh-dial ownership through callback unwind

## Reproduced baseline

The same seven public-API fixtures run against unchanged engine sources at
`83be0e7c9` and against the candidate. The baseline passes its successful raw
kernel transfer and ordinary proxy-refusal controls and fails five regressions:

- Connected lifecycle observer panic before session attachment.
- TLS-handshaking observer panic before the TLS API takes the descriptor.
- Reconnect's public clock hook panicking before attachment.
- An unrepresentable proxy deadline panicking during tunnel setup.
- Connected observer panic followed by another explicit dial.

Every failure finds an unreachable client descriptor and observes WouldBlock
from the loopback peer instead of EOF. The fixture records that original read
outcome, closes the unreachable baseline descriptor and then asserts, so failed
cases leave no leaked socket for the next case. Descriptor identification uses
the test's unique live endpoint and a borrowed process socket view; there is no
forced descriptor replacement. The baseline exits 101 with 2 passed, 5 failed,
0 ignored and no TLS resource skip.

The first fixture attempt did not compile: it used `verify_peer` instead of
the actual `verify_mode` API. Its source and diagnostics are retained. The
corrected fixture uses `VerifyMode::None` to reach the pre-handshake observer
without certificate material. That correction precedes the reproduced runtime
failures; the final positive run uses the same fixture bytes.

## Ownership boundary

`DialConnection` owns a fresh transport until transfer completes. The outer
guard spans the Connected observer and `Session::reconnect`'s clock callback.
Reconnect calls that hook before assigning its Io slot; the remaining reset
only clears plain buffers and protocol fields. The guard relinquishes its
temporary raw alias immediately when reconnect returns. The session continues
to expose the same raw Kernel/Zf/Sx variants and the existing shared TLS variant.

A kernel guard also spans proxy setup, SocketXtreme adoption and the
TlsHandshaking observer. It hands the descriptor to TLS before invoking
`Context::connect`, whose contract already closes every refusal. This avoids
adding a second closer around TLS failure. Ordinary proxy/adoption errors now
leave closure to the guard. TCPDirect's returned zocket is guarded at the outer
handoff; transport cleanup uses the existing Io close dispatcher.

Observer and clock panics propagate. Existing lifecycle publication, counters
and HA-fence policy remain in place; this work closes an unattached transport.
Callers retain their existing recovery/teardown responsibilities for attached
sessions. There is no Session destructor or new checkpoint-on-drop behavior,
no public enum/API addition and no per-message work or allocation. This record
makes no performance claim.

## Verification and retention

| Gate | Result |
|---|---|
| Unchanged engine with the final fixture | 2 controls passed, 5 regressions failed |
| Focused default/open ownership fixture | 7 passed each; no TLS resource skip |
| Complete integrated default Rust stage | 2,018 passed, 0 failed, 1 existing ignored builders doctest |
| Complete integrated open Rust stage | 1,831 passed, 0 failed, the same 1 ignored doctest |
| Strict all-target Clippy, `-D warnings` | Passed in both editions |
| API inventory, generated coverage, new fixture rustfmt, export scan | Passed |

Final gates use `3e52c8b81cc4e551454e2135e471247cef36aa68`, including the
upstream acceptor fixture's descriptor allocation and serialization fix,
shared numeric-range fixture and local Cargo configuration. All 365 Rust and
632 shared fixture/reference/
gate/consumer path-keyset and hash pairs match the verifier before and after
the run. Both selected stages report 1 ran, 0 failed, 0 skipped; PARTIAL names
the unselected monorepo stages. The seven named cases preserve raw transfer,
peer EOF, ordinary refusal and retry behavior. Complete Rust editions exercise
the existing TLS, proxy and fake TCPDirect/SocketXtreme lifecycle suites as well.

Publication preserves all 365 Rust and 632 shared input path-keyset/hash pairs.
Earlier integrated gates also pass before the local Cargo configuration arrives;
complete suites and strict Clippy are repeated after that addition. Benchmark
stability reporting in the separate workspace is included in the final input
pin. The diffs and input proofs are retained. This slice makes no benchmark claim.

Tests use Rust/Cargo 1.92.0 and Clippy the retained 1.93.1 sysroot. Scan's final
gates run serially at `-j8` with one test thread on isolated CPUs 10–19. Initial
strict-guard attempts repeatedly yield to shared-pool C++ compilers; their
interrupted captures remain separate. The final physical-host guard requires
at least 120 GiB total and 64 GiB available, caps observed foreign process RSS
at 16 GiB and yields to a compiler whose CPU affinity overlaps the reserved
pool. Smaller/WSL hosts cannot run with it. BEELINK2 runs no heavy job for this
slice. The final gates complete without relaxing any correctness timeout.

Source pins and snapshots, fixture identity, actual commands, negative baseline,
initial fixture compile error, interrupted attempts, complete reports/stdout/
stderr, Clippy logs, resource guards and the candidate/publication bundle are
retained under `~/archive/libhft/rust-initiator-dial-ownership-20261012` with
verified SHA256SUMS on BEELINK2, Scan and HP. The local packet includes Scan's
complete packet. No public API/coverage status is changed.

The full-parity plan's status summary is corrected to match its retained
2026-10-03 two-host shared-store HA/C2 proof. That proof is already complete;
production feed/order endpoints and venue/FIXP endpoint/session/schema
certification still require external evidence. None is supplied by this audit.
