# Public managed .NET canonical session qualification

## Actual production API

A new standalone consumer uses the unmodified public managed SDK throughout:
`ManagedSession.Create`/`RunOnce`, `IFastHandler`, SDK `Begin`/`AddRaw`/`Build`
and owner sends, the public application pre-send gate and SDK Logout. The
SDK owns connection/Logon, sequence numbers, framing, serialization, actual
transport writes and session administration. The adapter does not implement
a socket/session engine. `SessionContext` is a borrowed ref struct and is
never retained; only its peer id is copied. The server feed uses public
unsequenced application enqueue and the SDK's pre-send gate.

The new identity is `libhft-dotnet-managed-handler-canonical`, with compact
flavour `dotnet-pure+callback+complete-rtt`. Historical raw-peer, Native and
other profiles retain their original identities and grades. The input is
an explicit open SDK source, fast runtime, kernel TCP, no store and no
external dictionary. There is no SDK source patch or native engine dependency.
Every endpoint checks its actual loaded mappings and fails if `hftnet` is
loaded. Actual SDK callbacks must equal all incoming application frames.

## Clocks, causal work and bounded capture

Request/reply starts before the request body and SDK encoding/write, ending
after final required parsing, all owner extraction, folding and checks.
Tick preparation/enqueue is outside the sample. The public SDK pre-send hook
stamps its fully serialized W before transport write; each stamp matches an
actual completed outbound W observation. The end is the first instruction
of the server's public application callback before any benchmark view,
marker matching, extraction or checks. Tick has no ExecutionReport leg.
One monotonic `Stopwatch` domain and exact integer conversion are used.

Both roles capture exactly ten functional cycles before warmup and close
both streams before warmup starts. SDK/in-process counts and the full measured
owner sink/fold prove the later traffic without measured application I/O.
Callback state advances each complete exchange inside its callback, allowing
multiple buffered messages in one owner-loop pass without reusing a cycle.
All four owner/body vectors share the independent canonical specification.

The functional probe delays the actual SDK wire-observer path before handler
delivery and the required owner extraction. Actual checkpoints and raw samples
prove RTT includes both delays while tick selects callback entry before later
extraction. Ordinary runs have integer-zero probe, no trace and no per-sample
trace allocations. Probe results cannot borrow a normal timing grade.

## Actual builds and sessions on both hosts

The complete 909-file stripped harness has no engine, private or Git tree.
Both hosts build with SDK 10.0.112, target net8.0, two MSBuild jobs, disabled
build servers/shared compilation and session build roots. Each build has zero
warnings and zero errors. HP holds high-priority `isol`, SCAN normal `isol`;
these functional checks have no timing or Stage 5 grade. Full endpoint CPU
budgets are observed and verified; the inherited profile does not narrow them.

Each host passes twelve ordinary and twelve 2 ms probe pairs, covering all
four flows with warmup 5, 0 and 5. Ordinary cold replay refuses 133 corruptions;
probe replay refuses 28 more. This is 48 actual pairs and 322 refusals across
both hosts, with no skips. Each ordinary/probe matrix retains 240 primary,
240 delay samples and 1,000 application frames per peer. Four C# body/owner
vectors match the independent specification. Every endpoint remains free of
the native engine library. Source and SDK byte/mode inventories are unchanged.

All 1,018 focused SDK-free preflight/clock/affinity/runtime/writer/report/
comparison/queue/status controls pass without skips. The original producer's
raw filename, actual managed provider, zero native-library observation,
callback delivery, fast mode, dictionary/store posture, runtime version and
CPU placement are required before compact output. Generic physical collection
and cold replay support the distinct new identity through the existing root
helpers; no root policy/registration change is required. Whole-harness export
and timing admission remain independent gates.

## Immutable identities and retention

- Qualified source pin: `0bed00de9fc233dfcd2f443ac16980f22d3d90d5`.
- Complete source inventory SHA-256:
  `70313fb049d49e2be91bc0d710796435e67818b296be6e1c9e97f14bfde060be`.
- Driver DLL, identical on both hosts:
  `cadc27966c494347605915d41b749bb1ddc54c59f65c94fc87b4726d2c5f0c83`.
- Unpatched SDK content pin:
  `uncommitted-functional-source-26310f12584fd0f392af231da8c2ea10067f50bb337db118cc79a2895da54386`.

Original source and working roots on both hosts:

- `~/.cache/libhft/fullbench-dotnet-managed-session-20261017-v1`
- `~/build/codex-fullbench/libhft/dotnet-managed-session-20261017-v1`

Only this record and maintained harness source enter Git. Raw captures,
samples, runtime logs and source tarballs stay on the hosts. Fresh full physical
collection, report rate/stability/delay, matched .NET peer and whole-harness
release gates remain open. No timing or matched comparison is inferred here.

## First physical setup correction

The first DAC attempt exposes an omitted acceptor address: the SDK keeps its
loopback default when only its port is set. It produces no report/timing cell.
The separate corrected consumer explicitly binds the declared address and
passes 48 actual ordinary/probe pairs on `127.0.0.2` with 322 refusals. Original
failures and source pins remain retained; see the
[listener correction record](RECORD_2026-10-17_dotnet_managed_listener.md).
