From 8607f5d53084b38e4fe6b9a3e42bc4f34ca3a6a1 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 4 May 2026 22:29:45 -0400 Subject: [PATCH] CLAUDE.md: document cross-platform status Verified 2026-05-04: - SDK builds on Debian 13 with .NET 10 SDK 10.0.203 - ProbeAsync over RemoteTcpCertificate works from Linux - RemoteTcpIntegrated fails on Linux due to a WCF-level limitation (NetTcpBinding + Windows TcpClientCredentialType is BCL-Windows-only), not a HistorianSspiClient issue - Authenticated reads over the cert path with explicit creds are wired but await live verification Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 66fc3d1..6391de6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -89,6 +89,28 @@ End-to-end chain working from a pure managed .NET 10 client: `Hist.GetV → Hist `EnsureTagAsync` and `DeleteTagAsync` chain follow the same pattern as reads but require Open2 with `NativeIntegratedWriteEnabledConnectionMode = 0x401` (Process | Write | IntegratedSecurity) — the read-path's `0x402` (read-only) makes the server return err 132 `OperationNotEnabled` silently. The analog Float `CTagMetadata` payload is 144 bytes with a leading `0x4E` marker byte and a 2-byte trailer `FE xx` where the second byte is the ApplyScaling flag (`00` for false / `01` for true). The `IHistoryServiceContract2` surface has no `UpdateTags` operation — distinct MinRaw/MaxRaw persistence is achieved entirely by toggling that one byte in the EnsT2 payload, not via a follow-up call. See `docs/reverse-engineering/handoff.md` and the `WriteDiag` env-gated diagnostic helper in `HistorianWcfTagWriteOrchestrator` for capture details. +### Cross-platform status (verified 2026-05-04) + +The SDK builds and runs on Linux (Debian 13, .NET 10 SDK 10.0.203). `HistorianSspiClient` was rewritten on top of `System.Net.Security.NegotiateAuthentication` so the only remaining Windows-only surface is in WCF itself: + +- ✅ **Build** — clean on Linux (no platform-specific compile errors after the + P/Invoke removal). +- ✅ **`ProbeAsync` over `RemoteTcpCertificate`** from a Debian client + (10.100.0.35) against the Windows Historian (10.100.0.48) — TLS handshake + succeeds, server returns its version. +- ⚠️ **`RemoteTcpIntegrated`** fails on Linux at the WCF transport layer + (`SecurityNegotiationException → AuthenticationException`). `NetTcpBinding` + with `SecurityMode.Transport` + `TcpClientCredentialType.Windows` requires + Windows-only auth code in WCF that isn't ported to .NET on Linux. This is + a hard WCF limitation, not a `HistorianSspiClient` issue. The + `HistorianWcfBindingFactory.CreateMdasNetNamedPipeBinding` and + `CreateMdasNetTcpWindowsBinding` methods carry a `#pragma warning disable + CA1416` documenting this. +- ⏳ **Authenticated reads over `RemoteTcpCertificate` from Linux** — wired + to use NegotiateAuthentication's GSSAPI/NTLM path (`gss-ntlmssp` installed + on Debian), but live verification requires an explicit Windows credential + (`HISTORIAN_USER` / `HISTORIAN_PASSWORD`) which hasn't been exercised yet. + ### Remaining gaps Smaller, isolated items — none block the production read surface: