Lands M3 stream B raw opnum surface: an async NmxClient over the
mxaccess-rpc transport that dispatches all 9 INmxService2 procedures
(GetPartnerVersion, RegisterEngine2 + WithoutCallback, UnregisterEngine,
Connect, AddSubscriberEngine, RemoveSubscriberEngine,
SetHeartbeatSendInterval, TransferData) plus a NonZeroHresult error
variant that mirrors ThrowIfFailed (cs:563-574).
New
- crates/mxaccess-nmx/src/client.rs (~580 LoC, 8 tests including 5
real-socket tokio tests against a hand-rolled DCE/RPC server) — port
of the raw opnum surface from ManagedNmxService2Client.cs.
- NmxClient::connect builds the NTLM-packet-integrity bind path; for
tests, NmxClient::from_bound_transport accepts a transport bound any
way the caller likes (the test server doesn't validate signatures).
- fresh_orpc_this generates a per-call Cid via rand::random(), mirroring
the .NET reference's Guid.NewGuid() at every call site.
- NmxClientError::NonZeroHresult unifies the .NET reference's
Marshal.ThrowExceptionForHR + InvalidOperationException branches so
callers see one typed surface for "transport-OK + LMX rejected".
Cargo.toml: added tokio, tracing, thiserror, rand to mxaccess-nmx.
Two layers of the .NET reference are deliberately out of scope this
iteration; both logged as new followups in design/followups.md:
- F12 (P1): the auto-resolving Create() factory, which needs windows-rs
COM activation (gated by F6) + ComObjRefProvider port.
- F13 (P1): the high-level Write*/Advise*/UnAdvise/RegisterReference
helpers, which depend on GalaxyTagMetadata from M3 stream A (the
Galaxy SQL resolver crate, not yet started).
Test count delta: 389 -> 397 (+8). All four DoD gates green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lands the async DCE/RPC TCP client — the transport that bridges the M2
PDU codec to a real socket. Unblocks M3 stream B (mxaccess-nmx, the
NmxClient) and brings F9 (ResolveOxid wrappers) within reach.
New
- transport.rs (~700 LoC, 10 tests including 2 real-socket tokio tests)
— port of src/MxNativeClient/DceRpcTcpClient.cs.
- DceRpcTcpClient::connect/bind/bind_with_managed_ntlm_packet_integrity/
call/call_bound/call_bound_object — async over tokio::net::TcpStream.
- encode_packet_integrity_request: 4-byte 0xBB pad + 8-byte AuthTrailer
+ 16-byte NtlmClientContext::sign signature, frag_length and
auth_length rewritten in the embedded header per cs:201-250.
- encode_request_bytes: PFC_OBJECT_UUID flag (0x80) and inserted
16-byte object UUID slot per cs:269-278.
- TransportError enum unifies io / codec / NTLM / fault / not-connected
surfaces. Mirrors DceRpcFaultException as the typed Fault variant.
- NTLM_AUTH_CONTEXT_ID = 79232 = 0x13580 (cs:90,133) exposed publicly.
Deliberately skipped: BindWithNtlmConnect / BindWithNtlmPacketIntegrity
(SSPI flavours at cs:55-63,108-149) — those wrap .NET's
System.Net.Security.SspiClientContext, which has no portable analogue.
Managed-NTLM path covers what the production Rust client needs.
mxaccess-rpc/Cargo.toml: added tokio (workspace-pinned).
design/followups.md: F9 downgraded P1 → P2 (transport landed; only the
two pure-codec ResolveOxid wrappers remain).
Test count delta: 354 -> 364 (+10).
Open followups touched: F9 partially advanced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lands M2 wave 1 — three pure-Rust modules under crates/mxaccess-rpc with
60 unit tests. Each is a 1:1 port of one .NET reference file:
- ntlm.rs (1137 LoC, 19 tests) — `ManagedNtlmClientContext.cs`. NTLMv2
challenge/response, Type1/Type3 builders, sign() with RC4-sealed checksum
and per-call sequence advance. Manual `Debug` impl that hides credentials;
not Clone (rc4 0.2 cipher state is non-Clone). Pure-Rust crypto via
hmac/md-5/md4/rc4 v0.2/rand v0.8 (rc4 0.2 chosen per design/review.md:78).
- pdu.rs (1573 LoC, 33 tests) — `DceRpcPdu.cs` + auth-trailer types from
`DceRpcAuthentication.cs`. Bind/AlterContext/Auth3/Request/Response/Fault
PDUs, NDR20 transfer syntax, auth_value with 4-byte alignment padding,
preserved-byte fields per CLAUDE.md unknown-bytes rule.
- objref.rs (~470 LoC, 11 tests including a 366-byte captured OBJREF
round-trip) — `ComObjRef.cs`. MEOW signature, OXID/OID/IPID, dual-string
array with printable-ASCII escaping and security-binding boundary.
ComObjRefProvider.cs deferred (windows-rs Win32 wrapper — see F6).
Every wire-byte claim cites src/MxNativeClient/<file>.cs:LINE per
CLAUDE.md "no fabricated protocol behaviour" rule.
Test count delta: 217 → 277 (+60)
Open followups touched: F1–F8 (new — see design/followups.md)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>