# Classic journal recovery sequence bounds

The Rust classic FIX journal now rejects incompatible committed sequence numbers
before recovery can truncate a torn suffix or start a writer. Its generic FIXP
journal retains the signed 64-bit range. Java's generic journal now accepts an
owner-specific recovery limit too. Initially the classic Java session call site
was reserved and remained unresolved; the recovery-review owner subsequently
wired that limit in ad1f2b2b5. The constructor alone was not the complete fix.

These are cold recovery checks. The Rust outbound save also rejects the terminal
u32 sequence, matching its C++ and QuickFIX-store counterparts. No lock was added,
and no latency improvement or production incident is claimed.

## Reproduced failures

The baseline was `af52a52be`, with new Rust regression tests but unchanged runtime
sources. Five of seven tests failed. The remaining two established that the last
representable successor and the generic 64-bit journal already worked.

- A rejected outbound or inbound checkpoint caused a torn suffix to be truncated
  before the 32-bit classic store reported incompatibility.
- A later valid reset checkpoint hid an earlier incompatible checkpoint.
- A frame at u32::MAX was accepted although its successor cannot fit the classic
  session counter. The store also accepted a new save at that sequence.

The Rust fix checks every complete frame and every valid modern or legacy
checkpoint against the owner's range before any recovery write. It allows a next
sequence of u32::MAX but refuses frames at that value. Ordinary repair of a torn
suffix in a compatible journal remains supported. Failed opens release the
writer fences so a compatible 64-bit owner can retry.

The separate Java probe ran against freshly compiled, unchanged Java sources at
the same pin. It exercised modern and legacy checkpoints, outbound and inbound
overflow, with and without a torn suffix, and with and without a later reset.
All eight rejected opens modified the input: the session's refusal called the
normal close, which appended a 36-byte checkpoint. Recovery also removed a torn
suffix where present. All eight cases with a later reset were incorrectly
accepted. The probe closes accepted stores for cleanup; its total of 16 modified
files must not be misread as 16 rejected-open mutations.

This reproduces incompatible-input modification, not deletion of a committed
frame or an observed production outage. C++'s FileJournal already validates the
owner's range before tail repair and is the parity reference.

## Verification

- Rust development library: 926 passed, zero failed or ignored.
- Rust open library: 812 passed, zero failed or ignored.
- Java storage and provider parity selection: 88 passed, zero failed or skipped,
  including seven new direct recovery-limit tests, classic session restart tests,
  QuickFIX store tests and native provider checks.
- Export scrub scan: three changed engine files, zero findings.

These Rust runs use `cargo test --lib`; they do not claim integration or doc-test
coverage. Functional checks used shared or isolated CPU leases, sometimes while
other shared work overlapped. They are not quiet-host latency measurements.

The first Java verification used a stale JNI library and failed its ABI checks;
two new test assertions also incorrectly compared entire preallocated replay
buffers instead of their recorded lengths. Those assertions were corrected, the
JNI library was rebuilt through the normal Maven lifecycle, and all 88 tests
passed without skips. An earlier Rust full run had one diagnostic-wording
regression; preserving the classic store's 32-bit error context restored it.

Baseline sources, the Java probe, patches, verification output and publication
pins are retained in `~/archive/libhft/journal-sequence-recovery-review-20261003/`.
Post-rebase verification is retained separately.
After integrating the FIXP B2 changes at `3b2792739`, the full Rust library
counts are 942 development and 827 open, with no failures or ignored tests.
All 88 selected Java tests pass without skips in both editions after fresh
JNI builds. These higher Rust counts include upstream tests, not additional
regressions authored by this review.

## Frozen NIC staging inputs

The prepared managed NIC bundle remains the earlier verified artifact, not the
JNI library rebuilt for this review. Its 57 payload and installer/configuration
files were copied into
`~/archive/libhft/nic-20261002-managed-rust/prepared-payload.BRI7fD/`, checking each
against the original staging hashes before and after copying. The old JNI bytes
came from the matching, unchanged bench-stage kernel library. No new native
library was mixed into the old Java bundle.

The home helper now uses an archived root script rather than session scratch,
and all 59 current manifest entries refer to frozen payload files or the two
staging scripts. Syntax and hash checks pass. An unprivileged installer simulation
passed all eleven selected dispatch arms and compared the installed native bytes.
It substitutes ownership commands within its child process because real root
ownership cannot be applied by an unprivileged user; that ownership boundary is
not verified by the simulation. Its source and output are retained separately.
No root install or NIC run occurred in
this review; sudo staging remains required before those checks can resume.

## Completed Java call-site follow-up

The recovery-review owner published ad1f2b2b5: `PureJavaSession.AsyncFileReplayStore.open`
uses the six-argument FileStore constructor with Integer.MAX_VALUE as
`maxRecoveredNextSequence`; its defensive post-open range refusal uses
`closeWithoutCheckpoint()`. The owner also added 16 session-level recovery/HA tests.
This session's equivalent unpublished patch was parked rather than pushed over
that claim. Its initial 16-case probe returned zero mutations and zero incompatible
acceptances on the proposed patch. Integrated verification and the handoff patch
are retained under `~/archive/libhft/quickfixj-range-review-20261003/`; see the
separate QuickFIX/J sequence-range review record for final scope and pins.
Fresh integrated Java verification passed 107 development tests (including the
owner's 16 recovery/HA tests) and 91 edition-neutral open tests, zero failures or
skips. The existing 16-case probe passed in both editions with zero mutations
and zero incompatible acceptances; the two pro-only HA methods ran only in the
development selection.
