Add pluggable Logon authentication (FixLogon) for the FIX adapter - #418
Open
0-jake-0 wants to merge 1 commit into
Open
Add pluggable Logon authentication (FixLogon) for the FIX adapter#4180-jake-0 wants to merge 1 commit into
0-jake-0 wants to merge 1 commit into
Conversation
The FIX adapter only supported LMAX-style Username/Password (tags 553/554) in the Logon message. Venues like Binance authenticate with a signature computed over the Logon header, which the fixed encoder couldn't express. Add a generic `FixLogon` (None / Password / Custom) plus a `LogonContext` carrying the SenderCompID, TargetCompID, MsgSeqNum and the exact SendingTime string the Logon will carry. `FixSession::send_with` now computes the sequence number and SendingTime once and hands both to the field builder and the encoder, so a signer signs exactly what goes on the wire. SendingTime gains millisecond precision. `fix_connect_tls` is unchanged (delegates to a new `fix_connect_tls_logon` that takes a `FixLogon`). wingfoil stays free of any venue/crypto specifics — the Ed25519 signer lives in the caller. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q96qpjaqcpywW3rdy1eHjW
0-jake-0
added a commit
that referenced
this pull request
Jul 8, 2026
* fix: pluggable Logon authentication (FixLogon) for the FIX adapter The FIX adapter only supported LMAX-style Username/Password (tags 553/554) in the Logon message. Venues like Binance authenticate with a signature computed over the Logon header, which the fixed encoder couldn't express. Add a generic `FixLogon` (None / Password / Custom) plus a `LogonContext` carrying the SenderCompID, TargetCompID, MsgSeqNum and the exact SendingTime string the Logon will carry. `FixSession::send_with` now computes the sequence number and SendingTime once and hands both to the field builder and the encoder, so a signer signs exactly what goes on the wire. SendingTime gains millisecond precision. `fix_connect_tls` is unchanged (delegates to a new `fix_connect_tls_logon` that takes a `FixLogon`). wingfoil stays free of any venue/crypto specifics — the Ed25519 signer lives in the caller. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q96qpjaqcpywW3rdy1eHjW * Address PR #418 review: password test, hot-path alloc, naming, docs - Add password_logon_sends_username_and_password test guarding the FixLogon::Password path (tags 553/554) after the send_with refactor. - Avoid a per-message Vec/String clone on the send hot path: extract a shared write_encoded core so send() frames directly from the borrowed slice instead of round-tripping through send_with's builder. - Rename TAG_RESET_ON_LOGON -> TAG_RESET_SEQ_NUM_FLAG to match tag 141's real name (ResetSeqNumFlag), aligning the constant with its comment. - Note RawDataLength (tag 95) precedes RawData (tag 96) in the module and fix_connect_tls_logon docs, consistent with CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vum2BQHuMNkRUr8Wk1VVrp * Fix flaky zmq_first_message_not_dropped_no_delay: keep buffer once accepted The ZMQ publisher buffers messages until a subscriber connects (slow-joiner mitigation) and clears the buffer after BUFFER_TIMEOUT so a late subscriber doesn't receive stale backlog. The clear fired purely on wall-clock buffer age, even in the same cycle where check_monitor() had just observed the TCP ACCEPTED event but subscriber_connected was not yet set (still inside the ~50ms subscription-propagation wait). Under parallel CI load the publisher's graph cycles can be starved past BUFFER_TIMEOUT; the delayed cycle then observes the accept and immediately discards the buffer, dropping message 1 — the exact invariant the test asserts. Only clear the buffer while no subscriber has begun connecting (accepted_at.is_none()). Once an accept is observed we are committed to flushing to that subscriber. The anti-unbounded-growth guarantee is preserved: with no subscriber, accepted_at stays None and the buffer still clears every BUFFER_TIMEOUT. Verified: zmq integration suite green, and the previously-flaky test passes 20/20 under repeated runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vum2BQHuMNkRUr8Wk1VVrp --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the FIX adapter so a caller can supply a custom Logon authentication scheme, not just Username/Password. Adds a
FixLogonenum and aLogonContext, letting a venue attach a cryptographic signature (e.g. Ed25519) bound to the exact Logon bytes on the wire. wingfoil itself stays venue/crypto-agnostic.Changes
FixLogon—None/Password(String)/Custom(Arc<dyn Fn(&LogonContext) -> Vec<(u32, String)>>).LogonContext— exposes MsgType, SenderCompID, TargetCompID, MsgSeqNum, and the exact SendingTime string the Logon will carry, so a signer computes its payload over the canonical wire format.FixSession::send_with— computes the sequence number and SendingTime once and hands both to the field builder and the encoder, preventing skew between signature and wire bytes.SendingTimenow has millisecond precision.fix_connect_tls_logon— new public factory taking aFixLogon;fix_connect_tls(password: Option<&str>)is unchanged and delegates to it viaFixLogon::from.CLAUDE.md.Notes
wingfoil/src/adapters/fix/is touched. The requiredtest.rustcheck passes; thetest.integration.adapterred is a pre-existing Kafka integration flake unrelated to this change.🤖 Generated with Claude Code
https://claude.ai/code/session_01Q96qpjaqcpywW3rdy1eHjW
Generated by Claude Code