# Native .NET Logon reset retires the physical store epoch

Native .NET could acknowledge a FIX sequence reset at sequence 1 while its mmap
store still retained the previous epoch. Reopening recovered the old sequence 8
and old payload instead of the new next sequence 2. For portable and QuickFIX
file stores, a failed reset was detected only after the protocol had already
rewound its counters. One missing runtime-adapter reset hook caused both defects.

The adapter now delegates Logon resets to each concrete backend's existing
checked operation. A successful reset retires the old durable epoch; a failed
reset reaches the protocol before a reset-induced counter rewind or a Logon reply.
The writer descriptor and its existing HA lock remain owned throughout.

## Reproduced behavior

The source at `74e38529e` has the new fixtures but no implementation correction.
Each TLS build has **34 passes, 32 failures and zero skips** in the 66-case pro
fixture, and **18 passes, six failures and zero skips** in the 24-case open
fixture. The baseline is retained on the private branch
`s/codex-libhft-hp-logon-epoch-baseline-20261014`.

The mmap failure is visible at the first outbound FIX frame, not just inferred
from reading the code. A peer-requested reset, an acceptor's local ResetOnLogon
and an initiator's local reset all send Logon sequence 1. The runner reports next
outbound 2, but its store still reports 8 at that send. Independent reopen
recovers outbound 8 and the old payload at sequence 7. This fails twelve cases:
both mmap capacities, HA enabled/disabled and all three reset paths.

Twenty further pro cases drive real reset I/O failure on five durable
configurations: mmap capacities 4,096 and 65,536, portable file, QuickFIX C++
files and QuickFIX/J files, with HA enabled/disabled and peer-reset or
initiator-local reset. `RLIMIT_FSIZE=0` permits truncate-to-zero but refuses the
following resize or checkpoint write. Each case is a child process, with its
signal disposition and limit restored before observation and cleanup.

Mmap's generic reset incorrectly succeeds: it only clears the in-memory index,
so no physical reset is attempted and a Logon is emitted despite the I/O limit.
The other file stores reach an I/O error, but the generic hook discards their
reset result. Their later inbound checkpoint or outbound preparation refuses
the Logon after the counters have already become 1/2 or 1/1 instead of remaining
8/9. The six open-edition failures are these file-store fault cases without HA.

The remaining baseline cases are controls. File stores retire an epoch when
their reset succeeds; storeless and memory sessions reset normally; non-reset
Logons retain the old payload and continue its counters. HA contenders are
refused at transport visibility and while the failed-reset owner remains live.

## Fixture and correction

`test_native_peer_epoch_reset.cpp` includes the actual native implementation and
instantiates its `HftNetStore` in the ordinary `fix::Session` parser/protocol. Its
transport captures generated FIX bytes and observes store state at `SendMsg`.
It parses the reply's message type and sequence, then closes and independently
reopens the physical store to check both counters and old-payload membership.
The private companion adds both mmap capacities and durable HA controls.

The three successful reset paths are peer-requested acceptor reset, acceptor
ResetOnLogon and initiator ResetOnLogon. An acceptor's local-reset fixture admits
the peer's first Logon at inbound 1, as the configured lifecycle does, while
preserving the old outbound epoch until that Logon is accepted. Peer and
initiator reset-failure cases require ERROR, no emitted frame, inactive/faulted
state and unchanged 8/9 counters. This is actual parser/protocol execution with
captured frames, not a hand-written telemetry projection or a NIC test.

The production correction adds `HftNetStore::ResetForPeerLogon` and its
argument-dependent lookup customization. The old generic hook was intended for
memory stores: `Clear()` followed by unconditional success. Mmap's `Clear()`
only clears its RAM index; its concrete reset is `ResetInPlace`. The file
backends' concrete hooks inspect write/flusher failure as well as open state.
The adapter forwards to those hooks and retains normal memory/storeless behavior.

The shared protocol, reset validation, writer-lock operations, store format,
offline reset and send-before-persist ordering are unchanged. No new lock or
heap-allocation step is introduced in the adapter. The physical mmap reset is cold Logon
work; this qualification is functional, not a latency benchmark.

## Qualification

At corrected source `ed27fcd83`, **66/66 pro and 24/24 open cases pass**, with
zero skips, in each TLS build configuration. The same selections pass with GCC
11.5.0, 14.2.1 and 15.2.1 and Clang 21.1.8. Counts are per execution: the pro
companion includes the open fixture's cases, so they are not disjoint totals.

GCC 14 address and undefined-behavior sanitizers pass the same four edition/TLS
executions with leak checking enabled. The prior offline-reset readiness/lock
fixture remains green, twelve cases in each TLS build. Existing native durable
teardown, memory-store and QuickFIX-store fixtures pass in both TLS configurations.

The normal optimized production library passes the 37-case HA regression and
availability/edition selection on .NET 8.0.31 and 10.0.12. The development
selection passes 351/351 with zero skips: managed/native wire parity, store
interoperability, Logon identity/time, QuickFIX reset and native HA controls.
These execution counts overlap, rather than adding up to unique cases.

The open-edition selection passes 316/316 with zero skips. Its native library is
built separately through the normal Makefile, and availability/edition guards
are included in both selections. The boundary check compiles 145 open sources
without the 67 private sources and verifies six named refusal boundaries. The
registered concrete C++ mmap suite passes with production optimization and LTO,
including its epoch, reset-failure and writer-lock controls. The publication scan
reports zero findings in the three changed engine/test files. Source and driver
hashes still match at the end of qualification.

After fetch/rebase, every qualification input hash still matches. At clean
integrated pin `1c38f3007`, all 66 pro and 24 open native cases pass again in both
TLS configurations, and the full 351/316 binding selections pass with zero skips.
The binding reruns use the unchanged qualified production libraries and managed
assemblies in their normal build locations; source inputs and library hashes
are checked before/after. `integrated-logs.tar.gz` retains this pin and the TRX
reports.

The fixtures establish clean-reopen sequence/replay behavior and the local
writer fence during reset/failure. They do not establish power-loss durability,
multi-host store replication or a physical-NIC latency result. Failed destructive
resets can partly change disk contents; the error contract here is no Logon and
no premature counter rewind, not transactional restoration of the old file.

## Reproduction and retained evidence

[run-focused.sh](evidence/native-logon-epoch-20261014/run-focused.sh) takes a
session source root, absolute output root and `baseline` or `fixed`. It builds
through the registered native-test Makefile in both editions and both TLS build
configurations. Baseline requires the exact 32/six failures; fixed requires
66/24 passes and zero skips.

[run-qualification.sh](evidence/native-logon-epoch-20261014/run-qualification.sh)
adds four compilers, sanitizers, previous offline-reset and native-store controls,
normal production libraries, .NET runtime/edition and wire-parity selections,
the open-source boundary and the concrete C++ mmap reset controls. Wrap the
outer invocation in `host-cpu-slot` and keep a fresh output root per run.
[run-integrated.sh](evidence/native-logon-epoch-20261014/run-integrated.sh) takes
the source root, completed qualification root and fresh output root for the
source-bound final native and binding reruns.

Compressed logs beside the drivers retain source pins, implementation patches,
input/driver hashes, build commands, captured case outcomes and test reports.
Copies are retained under
`/home/yann/archive/libhft/native-logon-epoch-20261014/`; builds and runtime scratch
are under `/home/yann/build/codex-libhft-hp/libhft/native-logon-epoch-20261014/`.
