# Rust application Logout and run lifetime — 2026-10-13

## Contract

This completes item 1 of the October 12/13 ruling in
`docs/WIP_AGENT_CLAIMS.md`. An idle managed Logout request has no effect and is
never remembered by the next run. An active request before establishment stops
the run, closes any pending connection and suppresses Logon and redial. After
Logon, one Logout is written or queued and the existing confirmation deadline
is retained when another request arrives.

Caller-driven sessions expose `Session::logout() -> bool` and
`logout_text(Option<&[u8]>) -> bool`. True means one Logout was accepted for
writing or queuing. Inactive/repeated requests return false; an unanswered Logon
closes without a Logout. The owner still drives queued output and confirmation.
Managed initiator/acceptor handles retain their void request signature.

A private atomic signal gives each run an epoch. A request cannot move from an
ended run into its successor, and an owning guard clears the epoch on normal
return or panic. Public standalone `connect()` has the same scope; nested
`connect()` belongs to the surrounding run. TCP connect, proxy negotiation and
TLS waits check the signal between polling slices of about 50 ms; TCPDirect
checks it while pumping and retrying. Existing public transport signatures are preserved.
Synchronous hostname resolution is checked before and after the resolver call;
this change does not interrupt a resolver already inside the system library.
Store faults remain terminal `E_STORE`/Faulted even if Logout was requested.

The upstream public sender restriction and Logon identity work are retained.
`session.rs` is unchanged by this slice. The former recovery blocker was resolved
upstream by correcting the expectations in `cea09afe7`; the owners agreed in
`43bcaf37e` to retain the existing recovery ordering. The October 12 proposed
patch is retired and unapplied. Its draft observations remain in
[the historical record](RECORD_2026-10-12_rust-application-logout.md).

## Source and tests

Qualified source: `e79ae5dd10dc389c7046fdf4d7fdd9477b584e5a`, based on
`587a45440c0712f1b4db9cb6dc7b9c2d1743419b`. The packet pins **374 Rust** and
**632 shared** input paths and SHA-256 hashes. Final publication is compared
against both complete maps after rebasing; documentation-only changes do not
alter the qualified runtime.
The prepublication pin and draft histories are retained in the source bundle;
the final runtime and records publish together in one commit.

The stage metadata reports a dirty worktree because this private record was
being updated during the gates. The retained status proof identifies that sole
modified path; the before/after maps qualify the exact unchanged Rust/shared
inputs, independently of the record's edits.

`application_logout` has **27** raw-peer/transcript tests, including the manual
five-state operation, Text preservation, queued output, repeat deadlines,
application hooks and protocol refusal. New cases exercise ignored requests
before/after a run, stop from Connecting/Connected, an actual pending TCP SYN,
a silent proxy, a silent TLS peer, schedule wait, panic cleanup, standalone
connect, an acceptor's idle request and terminal Logout store failure. TCP uses
a full accept queue to hold the second connect pending. TLS observes an actual
ClientHello before requesting the stop. Proxy observes the actual CONNECT
headers. All three require prompt closure and no reconnect; cancellation is
not counted as a dial or TLS failure. The peers build and check FIX framing and
never use another Rust Session to answer automatically. Watchdogs are bounded
and joined. Existing configured-startup tests now require an idle Logout to
leave the next startup and its store error observable. The five existing
`transport_lifecycle_review` cases preserve confirmation, original deadline,
mixed states, zero timeout and force-cancel assertions. Their graceful requests
now follow an application-hook acknowledgement of a Heartbeat processed inside
the active run, rather than a request made before the run began.

Five draft failures are retained: `591da1273` passed 26/27 focused cases but its
silent TLS fixture used the default verifier without a CA; `b4b62d8db` passed
27/27 plus 18/15 startup cases, then the full library build found a duplicate
test-module Arc import. At `9e6114a29`, the library and earlier integration
targets passed, then four older acceptor shutdown fixtures timed out because
they requested Logout before `run()` and relied on the former idle memory. The
active-run acknowledgement corrects those fixtures while preserving their
original behavior assertions. The first acknowledgement draft (`487855f39`)
called a nonexistent heartbeat convenience method; the final fixture uses the
existing public frame writer and preserves peer sequence tracking. At
`0b90462f5`, both complete stages pass 2,183/1,991, then strict Clippy rejects a
redundant Boolean clause in the proxy poll result. The final source simplifies
that clause with the same short-circuit evaluation. All five failures are
corrected before final qualification.

Review then found that returning from each proxy polling slice could consume a
response-parser pass and exhaust that budget during a long configured timeout.
The slices now remain inside the wait helper until readiness, interruption,
Logout or the configured deadline. The superseded `34fc01075` run passed the
default stage, then its open stage was stopped; it is not a final qualification.
`bacf96f81` passes both strict Clippy editions; its full gate was stopped when
upstream FIXP capacity checks and two regression cases landed. The final
qualification includes those upstream changes and repeats both complete stages.

## Qualification

| Gate | Default | Open |
|---|---:|---:|
| Application Logout focus | 27 pass | 27 pass |
| Configured startup focus | 18 pass | 15 pass |
| Existing acceptor shutdown focus | 5 pass | 5 pass |
| Complete Rust conformance stage | 2,185 pass | 1,993 pass |
| Ignored cases in the complete stage | 1 builders doctest | 1 builders doctest |
| Strict all-target Clippy (`-D warnings`) | pass | pass |

There are no failed tests or skipped Rust stages. Each selected stage reports
1 ran / 0 failed / 0 skipped. The conformance wrapper's exit 2 / PARTIAL refers
to the other unselected monorepo stages; this does not claim a complete monorepo
suite run. Commands, Cargo output and JSON are retained. The inventory check,
all 13 inventory tests, generated coverage check, scoped rustfmt and diff check
pass. Public export scanning finds zero issues in the 14 edited engine/tool
files.

## Resources and retained evidence

Draft focus and failed full gates ran on HP under an exclusive `isol-no-shared`
lease, CPUs 0–1 and `-j2`, with its 8 GiB start / 5 GiB stop memory guard.
The corrected gate was queued behind other sessions and stopped before any
heavy work. Final focus, full stages and strict Clippy run serially on BEELINK2
after its other heavy work ended, with 42 GiB available at start. Each build uses
`-j2`, one test thread and no dev/test debug information. The guard requires
24 GiB available before starting and stops only its own child group below
16 GiB or when foreign heavy work appears. Cargo, Rust and Clippy are the
installed 1.93.1 / 0.1.93 toolchain; HP's draft tests used Rust 1.92.0.
`LIBHFT_BUILD_ROOT` is `~/build/codex-libhft/libhft`; Cargo's configured automatic
intermediate build directory also stays outside the worktree. No in-tree build
products are created.

Evidence is kept under `~/archive/libhft/rust-logout-lifecycle-20261013` on
BEELINK2, HP and Scan: source bundle, input maps, command/output/JSON captures,
failed draft logs, helper scripts and checksum verification. Topic scratch is
removed after all three archives verify. Ordinary parity worktrees/build
caches remain available for the next slice.

Static scores remain 82/82 applicable APIs, 27/27 protocol rows and 43 complete
subsystems, with the two existing live endpoint/venue and FIXP certification
partials. This is software lifecycle qualification. The physical TCPDirect and
ibverbs proofs remain the earlier hardware records; no physical NIC rerun or
live venue certification is claimed here.
