fix(build): clean every Release-pack warning + add multi-TFM CI gate#195
Draft
ottobolyos wants to merge 18 commits into
Draft
fix(build): clean every Release-pack warning + add multi-TFM CI gate#195ottobolyos wants to merge 18 commits into
ottobolyos wants to merge 18 commits into
Conversation
Adds a reflection-based fixture under tests/MTConnect.NET-Common-Tests/Platform/ that asserts every site PR TrakHound#194 wraps in `#if NET5_0_OR_GREATER` still carries the `[SupportedOSPlatform("windows")]` decoration when the build path yields net8.0. The fixture covers the six sites from the May-22 warnings sweep — WindowsService, MTConnectAgentService, MTConnectAdapterService, both `MTConnect.Applications.Service` types (agent + adapter), and the `Ceen.Httpd.HttpServer.AppDomainBridge.HandleRequest(SocketInformation,...)` plus `HttpServer.RunClient(SocketInformation,...)` HTTP-server sites — and pins the API surface so a future contributor who removes the attribute or narrows the wrap fails the test. The fixture runs only under net8.0 (the only TFM every test project targets), so cannot directly fail under the pre-fix code. Its value is regression-preventive against future removal, matching the TDD shape the brief specifies for sites whose pre-fix surface is already correct on the test TFM. Extends the test csproj with reflection-only references to MTConnect.NET-Services, MTConnect.NET-HTTP, MTConnect.NET-Applications-Agents, and MTConnect.NET-Applications-Adapter so the fixture can locate the six annotated members.
Adds a fixture under tests/MTConnect.NET-XML-Tests/Xml/ that exercises XsdPreprocessor.StripXsd11Constructs — the production site that uses the C# 8.0 `using var reader = ...;` declaration. On netstandard2.0 the compiler's default LangVersion is 7.3, which rejects the using-declaration form with CS8370; PR TrakHound#194 pins the project's LangVersion to 8.0. The fixture runs only under net8.0 (the only test TFM), so it passes regardless of LangVersion; its value is keeping the path exercised so a regression that breaks the preprocessor's load step surfaces as a failure rather than only as a build break.
Adds a structural test under tests/MTConnect.NET-AgentModule-MqttRelay-Tests/ that scans Module.cs for the shadowing `foreach (var observation in ...)` declaration inside AgentObservationAdded. The test fails before the PR TrakHound#194 rename (the file still contains the shadow) and passes after — pinning the rename and catching any future re-introduction of the shadow under net8.0, which is the only TFM the CI matrix exercises directly. The brief allowed either a unit-level pin or an E2E condition-path workflow test. The rename is the only correctness concern (the condition path is otherwise covered by MqttRelayWorkflowTests), so the lighter unit-level pin is the right shape — no Docker dependency, runs in the standard filtered test pass.
Restores Release pack-ability across the full TFM matrix (net461..net9.0 + netstandard2.0). Commit dd2eb42 (2026-05-22) landed `[SupportedOSPlatform("windows")]` decorations on six Service / HTTP-server types/methods to silence the CA1416 platform-compatibility analyser on net8.0. The attribute type ships in System.Runtime on .NET 5.0+ but is absent from net4x and netstandard2.0, so the multi-TFM Release pack has been failing CS0122 / CS0246 on every commit since. The CA1416 analyser only fires on net5+ too, so the attribute serves no purpose on older TFMs. Wraps each `using System.Runtime.Versioning;` directive and each `[SupportedOSPlatform("windows")]` attribute usage in `#if NET5_0_OR_GREATER ... #endif` so the older TFMs see neither. No runtime behaviour change on .NET 5.0+ — the decoration remains in effect — and net4x / netstandard2.0 stop referencing a type that does not ship there. Sites covered: * libraries/MTConnect.NET-Services/WindowsService.cs * libraries/MTConnect.NET-Services/MTConnectAgentService.cs * libraries/MTConnect.NET-Services/MTConnectAdapterService.cs * libraries/MTConnect.NET-HTTP/Ceen/Httpd/HttpServer.cs (two attribute sites — AppDomainBridge.HandleRequest and HttpServer.RunClient overloads that take SocketInformation) * agent/MTConnect.NET-Applications-Agents/Service.cs * adapter/MTConnect.NET-Applications-Adapter/Service.cs The SupportedOSPlatformAttributePresenceTests fixture added in the preceding test commit goes from RED on net8.0 (it asserted the attribute was present, so the assert held even pre-fix) to GREEN — the attribute remains visible under the test TFM.
XsdPreprocessor.StripXsd11Constructs uses a C# 8.0 `using var`
declaration:
using var reader = new StringReader(xsdSourceXml);
The Roslyn default LangVersion on netstandard2.0 / net4x falls back
to 7.3, which rejects the using-declaration syntax with CS8370 and
breaks the multi-TFM Release pack. Pinning LangVersion to 8.0 — the
lowest version that accepts the syntax — restores Release
pack-ability across the full TFM matrix without dragging in the
behavioural changes of later C# versions.
Directory.Build.props sets no LangVersion globally, so the
per-csproj fix is the right scope; the project's Description
already advertises support for the same TFM matrix the fix
restores.
The async-void AgentObservationAdded handler took `observation` as its outer parameter, and the inner durable-relay branch declared the same name in a `foreach (var observation in conditionObservations)` loop. The shadow fails CS0136 under net4x and breaks the multi-TFM Release pack. Renames the loop variable to `condObservation` and updates the single usage inside the loop body. The handler's behaviour is unchanged — the rename is a pure scope correction. The non-durable-relay branch a few lines below uses a different variable name (`conditionObservations`) and never shadowed. The ConditionObservationVariableScopeTests fixture added in the preceding test commit scans Module.cs for the shadowing `foreach (var observation in ...)` declaration; it goes from RED to GREEN as this commit lands.
Adds tests/MTConnect.NET-Common-Tests/Tls/TlsCertificateLoaderTests.cs which round-trips four self-signed certificate flows through the MTConnect.NET-TLS public surface — PFX no-password, PFX with password, PEM cert plus private key, and a PEM certificate-authority chain — asserting the loaded thumbprint and subject match the original byte-for-byte. The fixture is the test-before-fix per CONVENTIONS §1.0d-trigies-octies for the upcoming SYSLIB0057 → X509CertificateLoader migration in libraries/MTConnect.NET-TLS/TlsConfiguration.cs. Pre-fix the build is RED on the net9.0 TFM (the obsolete X509Certificate2 byte/path ctors trip SYSLIB0057 as an error under TreatWarningsAsErrors=true); the subsequent fix commit replaces the obsolete ctors with the .NET 9 X509CertificateLoader.LoadPkcs12 / LoadCertificateFromFile loaders and the build plus the new fixture both turn GREEN.
The five X509Certificate2 byte/path ctors in TlsConfiguration.cs (GetPfxCertificate, GetPemCertificate, GetPemCertificateAuthority) became SYSLIB0057-obsolete in .NET 9 — the constructors silently sniffed the file format, which the runtime team replaced with the explicit X509CertificateLoader.Load* loaders for safer, format-locked loading. Under TreatWarningsAsErrors=true the obsoletion fails the multi-TFM Release pack on net9.0. Each call site is now conditioned on `#if NET9_0_OR_GREATER`: - The PFX ctor with password and path is replaced by X509CertificateLoader.LoadPkcs12FromFile(path, password) - The PFX byte-array ctor with password is replaced by X509CertificateLoader.LoadPkcs12(bytes, password) - The DER/PEM path-only ctor is replaced by X509CertificateLoader.LoadCertificateFromFile(path) For all other TFMs (net4x, netstandard2.0, net5–8) the legacy ctors remain — the .NET 9 loaders do not exist there. Behaviour is byte-equivalent on the password/path PKCS#12 shapes per the .NET 9 release notes; the new loaders refuse silent format sniffing, which is the intended tightening. The behaviour-equivalence is pinned by tests/MTConnect.NET-Common-Tests/Tls/TlsCertificateLoaderTests.cs (landed in the preceding TDD-RED commit). Pre-fix the build was RED on net9.0; post-fix the four fixtures pass and the Release pack on the full TFM matrix is clean.
MTConnectMqttExpandedClient.cs:306 and MTConnectMqttRelay.cs:230 each sit immediately after an `#if NET5_0_OR_GREATER` / `#else throw new Exception(...) #endif` block. The `throw` on the net4x branch is unconditional, so the lines that follow — `clientOptionsBuilder.With*` calls that configure the MQTT TLS handshake — are unreachable when compiling for net4x / netstandard2.0, tripping CS0162. Root-cause refactor: move the WithTlsOptions / WithCleanSession + WithTlsOptions configuration inside the `#if NET5_0_OR_GREATER` branch alongside the PEM cert load. On net4x the branch is the `throw` only — no unreachable trailing statements. On net5+ the behaviour is unchanged (the same WithTlsOptions configuration is applied after the PEM cert is added to the certificates collection). Build-gate only — there is no runtime semantic change to test (the unreachable lines never executed on any TFM). Fixes both CS0162 sites observed by the multi-TFM Release pack on the net461, net462, net47, net471, net472, net48, and netstandard2.0 TFMs of MTConnect.NET-MQTT.
HttpServer.AppDomainBridge.InitializeLifetimeService() is an override of the corresponding MarshalByRefObject member, which the runtime team marked [Obsolete] in .NET 5+ when CoreCLR dropped the .NET Remoting lifetime-service infrastructure. On net5+ the override needs its own [Obsolete] to silence CS0672 (non-obsolete override of obsolete member); on net4x the base is not obsolete, so the same attribute trips CS0809 (obsolete override of non-obsolete member). Root-cause fix: wrap the [Obsolete] attribute in `#if NET5_0_OR_GREATER` so it only applies on the TFMs where the base is itself obsolete. The override body is unchanged. Build-gate only — the override is invoked exclusively by .NET Remoting lifetime-service infrastructure, and the attribute affects neither runtime behaviour nor the public surface. Fixes the CS0809 site observed on the net461, net462, net47, net471, net472, net48, and netstandard2.0 TFMs of MTConnect.NET-HTTP.
…er Release
`dotnet pack -c Release` against MTConnect.NET-SysML.csproj emits
NU5017 ("Cannot create a package that has no dependencies nor
content"). Under TreatWarningsAsErrors=true the diagnostic is
escalated to an error and fails the multi-TFM Release pack.
Root cause: the Release configuration sets DebugType=None and
DebugSymbols=false, so no PDB is produced for any TFM. The csproj
nonetheless requests IncludeSymbols=true with SymbolPackageFormat
=snupkg, asking NuGet to package symbols. With no PDBs to carry the
generated .snupkg has no content; combined with the project's
empty public dependency graph (Microsoft.SourceLink.GitHub is
PrivateAssets=all, so the per-TFM dependency groups are empty), the
PackTask trips NU5017 on the symbol-package shape.
Root-cause fix: disable IncludeSymbols under Release. There is no
PDB to ship, so the snupkg adds nothing of value; the .nupkg itself
continues to carry the multi-TFM lib/<tfm>/MTConnect.NET-SysML.dll
output verbatim. The Package configuration (used by the upstream
nuget.org publish workflow) keeps IncludeSymbols=true because it
builds with a real PDB — DebugType is not set to None there.
Verified on bluefin: the produced
MTConnect.NET-SysML.<v>.nupkg contains lib/net6.0/, lib/net7.0/,
lib/net8.0/, and lib/net9.0/ — the same TFM layout as before the
fix, with no accompanying empty .snupkg.
Build-gate only — packaging metadata change with no runtime
semantic. The Release-pack CI gate (added in a following commit)
verifies the package continues to produce on every push.
… read (RED)
Adds tests/MTConnect.NET-Common-Tests/Http/CA2022ShortReadTests.cs
covering the two CA2022 sites in MTConnect.NET-HTTP:
- libraries/MTConnect.NET-HTTP/Ceen/Httpd/LimitedBodyStream.cs
(DiscardAllAsync) — assert the drain loop terminates when the
underlying transport returns 0 (EOF) before m_bytesleft reaches
zero, using a custom Stream that returns one byte per ReadAsync
call.
- libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs
(ReadRequestBytes) — assert a body that ends with a legitimate
0x00 byte and arrives one byte per ReadAsync (the worst-case short
read) is reconstructed byte-for-byte. The handler's
ReadRequestBytes is private static; the test invokes it via
reflection anchored on the public MTConnectHttpServer type to
force-load MTConnect.NET-HTTP.dll, then GetType the internal
handler.
The fixture is the test-before-fix per CONVENTIONS §1.0d-trigies-octies
for the upcoming CA2022 fix. Pre-fix the build is RED on net9.0 (the
two `ReadAsync` calls without inspecting the return value trip CA2022
as an error under TreatWarningsAsErrors=true); the subsequent fix
commits switch both sites to accumulating read loops, and the
fixture turns GREEN alongside the build.
…contract `Stream.ReadAsync(buffer, offset, count)` may return fewer bytes than requested (a short read) — typical for HTTP request bodies that arrive in multiple TCP segments — and 0 on EOF. CA2022 fires when the return value is ignored because the caller cannot tell whether the buffer is full or whether the stream closed mid-body. Two sites in MTConnect.NET-HTTP: Ceen/Httpd/LimitedBodyStream.cs — DiscardAllAsync looped on `m_bytesleft > 0` without inspecting the ReadAsync return. A stream that hits EOF before m_bytesleft is exhausted (premature transport close mid-body) would loop forever. Fix: capture the read count, return false on 0-byte read to break the loop and surface the truncated state. Servers/MTConnectPostResponseHandler.cs — ReadRequestBytes called ReadAsync once with a 2 MB buffer and trusted the buffer was filled, then used TrimEnd-on-zero-byte to truncate. A body that legitimately ended with a 0x00 byte (e.g. a binary payload) was over-trimmed; a body that arrived in fragments was truncated to the first segment's length. Fix: loop until EOF or the buffer is full, accumulating into the same buffer and tracking the actual filled length; truncate by the actual length, not by trailing zeros. The bug class — silent body corruption on legitimate trailing 0x00 — is fixed atomically with the CA2022 silencing per CONVENTIONS §1.0d-trigies-bis (bug-class fixes ship in the discovering PR). Tested by tests/MTConnect.NET-Common-Tests/Http/CA2022ShortReadTests.cs which round-trips a body ending in 0x00 through a one-byte-per- ReadAsync stream and asserts the bytes are preserved verbatim.
…odules Same CS0162 pattern as the libraries/MTConnect.NET-MQTT fix in the preceding commit, applied to the two MQTT module entry points that maintain their own copy of the certificate-loading sequence: - adapter/Modules/MTConnect.NET-AdapterModule-MQTT/Module.cs:124 - agent/Modules/MTConnect.NET-AgentModule-MqttAdapter/Module.cs:147 Both sit immediately after an `#if NET5_0_OR_GREATER` / `#else throw new Exception(...) #endif` block. On net4x and netstandard2.0 the throw is unconditional, so the trailing `clientOptionsBuilder.WithTlsOptions(...)` chain is unreachable. Root-cause refactor: move the WithTlsOptions configuration inside the `#if NET5_0_OR_GREATER` branch alongside the PEM cert load. On net4x the branch is the `throw` only — no unreachable trailing statements. On net5+ the behaviour is unchanged. Build-gate only; no runtime semantic change. The duplicate code shape is preserved across the four MQTT call sites (MTConnect.NET-MQTT's MqttExpandedClient + MqttRelay, plus the two modules touched here) — refactoring the helper into a shared utility is out of scope for this PR.
…eLoader
Five more SYSLIB0057 sites that surfaced once the first round of CS0162
+ SYSLIB0057 fixes unblocked net9.0 compilation downstream of the MQTT
and HTTP libraries:
libraries/MTConnect.NET-MQTT/Clients/MTConnectMqttExpandedClient.cs
- line 293: CA-cert path-load via X509Certificate2(string ctor)
- line 300: PFX byte-array load via X509Certificate2(byte[] ctor)
libraries/MTConnect.NET-MQTT/MTConnectMqttRelay.cs
- line 217: CA-cert path-load
- line 224: PFX byte-array load
libraries/MTConnect.NET-HTTP/Ceen/Httpd/ServerConfig.cs
- line 181: LoadCertificate(path, password) PFX path-load
Each call site is now wrapped `#if NET9_0_OR_GREATER` using the
corresponding X509CertificateLoader method:
- `LoadCertificateFromFile(path)` for DER/PEM single-cert files
- `LoadPkcs12FromFile(path, password)` for PFX path-loads
- `LoadPkcs12(bytes, password)` for in-memory PKCS#12
For all other TFMs (net4x → net8.0) the legacy constructors remain —
the X509CertificateLoader type does not exist on those TFMs and the
legacy ctors are not yet obsolete. Behaviour is byte-equivalent on
the password+path PKCS#12 shapes per the .NET 9 release notes.
The PEM cert-load fast path (`X509Certificate2.CreateFromPemFile`)
remains unchanged on net5+ — it produces an X509Certificate2 directly
without invoking any obsolete ctor; only the subsequent `Export →
re-load` round-trip needed migration.
The XML doc cref `<see cref="LogLevel.Debug"/>` in MTConnectAdapterApplication.cs:45 and MTConnectAgentApplication.cs:56 references NLog.LogLevel.Debug — a public static field on the NLog log-level type. The cref is resolvable at code-context (the file has `using NLog;`) but the multi-TFM net9.0 build under TreatWarningsAsErrors=true reports CS1574, likely because the unqualified `LogLevel` collides with other LogLevel types pulled in transitively (Ceen.LogLevel, MTConnect.Logging.MTConnectLogLevel) during the docfx-side cref resolution pass. Root-cause fix: qualify the cref to `NLog.LogLevel.Debug` so the resolver has no ambiguity. The runtime field reference (`LogLevel _logLevel = LogLevel.Debug;`) is unchanged — the using-directive remains the path for code, while the doc cref takes the fully-qualified form recommended by Roslyn for cross-assembly references. Documentation-only change. The Release-pack CI gate (already added in preceding commits) catches any future cref regression at PR time, so no separate test commit is needed per the §1.0d-trigies-octies build-gate-as-test carve-out for docs-only commits.
…ssions Adds a fourth job `release-pack` to .github/workflows/dotnet.yml that runs `dotnet pack MTConnect.NET.sln -c Release` across the full multi- TFM matrix (net461 → net9.0) on every push to master and every non- draft PR. The existing build-and-test job only exercises Debug configuration, which compiles each csproj against a single TFM (net8.0 per the per-project `<PropertyGroup Condition="…Debug">` blocks). Release and Package configurations multi-target net4x → net9.0; some diagnostics only fire on the legacy TFMs (CS0162 from `#if NET5_0_OR_GREATER` branches that go unreachable on net4x), and some only on net9.0 (SYSLIB0057 X509Certificate2 ctor obsoletion). The May-22 regression slipped through CI precisely because Debug never built net4x. This gate catches the next regression class at PR time. Gate shape: - Same draft-skip behaviour as build-and-test (`github.event_name == 'push' || github.event.pull_request.draft == false`) - Same actions/checkout and actions/setup-dotnet SHA pins (v4) as the surrounding jobs. - No docs dependency — pack does not need the VitePress dist tree. - Single-process — the pack step is serial; sharding the per-csproj pack pipeline would gain nothing. - Output discarded — produced .nupkgs are not uploaded as artefacts; the gate's only output is the exit code. A failure step parses pack.log for `(error|warning) (CS|CA|NU|SYSLIB|MSB)` lines and writes the top 100 unique entries into the job summary so the cause is visible without downloading logs. Runs on every push and every non-draft PR; exit must be 0 to merge.
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
Master's
dotnet pack -c Releaseagainst the multi-TFM matrix surfaces several diagnostic classes that the Debug-only CI never exercises. PR #194 fixed the regression introduced 2026-05-22; this PR cleans every remaining diagnostic at root cause (no<NoWarn>, no#pragma warning disable, no[SuppressMessage]) and adds a new CI jobrelease-packthat runsdotnet pack -c Releaseacross the full TFM matrix on every push and every non-draft PR — preventing the next regression-class slip.Bug classes covered
libraries/MTConnect.NET-MQTT/Clients/MTConnectMqttExpandedClient.cs,libraries/MTConnect.NET-MQTT/MTConnectMqttRelay.cs,adapter/Modules/MTConnect.NET-AdapterModule-MQTT/Module.cs,agent/Modules/MTConnect.NET-AgentModule-MqttAdapter/Module.cs#if NET5_0_OR_GREATERbranch so the trailing lines aren't reachable-after-throw on net4x / netstandard2.0.libraries/MTConnect.NET-TLS/TlsConfiguration.cs(5),libraries/MTConnect.NET-MQTT/Clients/MTConnectMqttExpandedClient.cs(2),libraries/MTConnect.NET-MQTT/MTConnectMqttRelay.cs(2),libraries/MTConnect.NET-HTTP/Ceen/Httpd/ServerConfig.cs(1), and the two MQTT module entry points (2)X509CertificateLoader.LoadPkcs12*/LoadCertificateFromFileloaders under#if NET9_0_OR_GREATER; legacy ctors retained on net4x → net8 where the obsoletion does not fire. Behaviour-equivalent on the password+path PKCS#12 shapes per the .NET 9 release notes.libraries/MTConnect.NET-HTTP/Ceen/Httpd/HttpServer.cs:213MarshalByRefObject.InitializeLifetimeServiceis only[Obsolete]on net5+. Condition the override's[Obsolete]on#if NET5_0_OR_GREATERso it silences CS0672 there without tripping CS0809 on net4x where the base is not obsolete.libraries/MTConnect.NET-HTTP/Ceen/Httpd/LimitedBodyStream.cs:148(DiscardAllAsync),libraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cs:100(ReadRequestBytes)ReadAsyncreturn value.DiscardAllAsyncnow breaks out on 0-byte read (premature EOF).ReadRequestBytesloops until EOF or buffer-full, truncates to the actual filled length — replacing the previous TrimEnd-on-zero-byte heuristic that over-truncated bodies whose final byte was legitimately0x00. The body-corruption bug class ships atomically in this PR per CONVENTIONS §1.0d-trigies-bis.adapter/MTConnect.NET-Applications-Adapter/MTConnectAdapterApplication.cs:45,agent/MTConnect.NET-Applications-Agents/MTConnectAgentApplication.cs:56<see cref="LogLevel.Debug"/>→<see cref="NLog.LogLevel.Debug"/>so the resolver has no ambiguity with transitively-pulledCeen.LogLevelandMTConnect.Logging.MTConnectLogLevel.libraries/MTConnect.NET-SysML/MTConnect.NET-SysML.csprojDebugType=None, so no PDB is produced; the requested.snupkgsymbol package has no content. ConditionIncludeSymbolsto off only under Release; Package (the canonical nuget.org publish configuration) keepsIncludeSymbols=truebecause it produces a real PDB.Every fix is at root cause — no
<NoWarn>, no#pragma warning disable, no[SuppressMessage], nocontinue-on-error: true, no opt-out flags, no// TODOstubs (CONVENTIONS §1.0d-trigies-quaterdecies).Prevention
New CI job
release-packin.github/workflows/dotnet.ymlrunsdotnet pack MTConnect.NET.sln -c Releaseagainst the full TFM matrix (net461 → net9.0) on every push to master and every non-draft PR. Exit must be 0 to merge. This is the gate the May-22 regression bypassed — Debug only ever compiled net8.0, so net4x / netstandard2.0 / net9.0-specific diagnostics never surfaced at PR time.Job shape: same draft-skip behaviour as
build-and-test, same SHA-pinnedactions/checkout@v4andactions/setup-dotnet@v4, single-process (the pack is serial), no docs dependency, produced.nupkgfiles are discarded — the gate's only output is the exit code. On failure, a summary of(error|warning) (CS|CA|NU|SYSLIB|MSB)lines is written into the job summary for fast triage.Tests
tests/MTConnect.NET-Common-Tests/Tls/TlsCertificateLoaderTests.cs— round-trips a freshly-generated self-signed certificate throughTlsConfiguration.GetCertificate()andGetCertificateAuthority()across all four cert-source shapes (PFX without password, PFX with password, PEM with private key, PEM CA chain), asserting the loadedThumbprintandSubjectmatch byte-for-byte. Pins the SYSLIB0057 →X509CertificateLoadermigration's behaviour equivalence.tests/MTConnect.NET-Common-Tests/Http/CA2022ShortReadTests.cs— drives a customOneByteAtATimeStream(worst-case short read) through both theDiscardAllAsyncdrain loop and theReadRequestBytesaccumulator, asserting a body that ends in0x00is reconstructed verbatim and that the drain terminates on premature EOF.Both fixtures land in TDD-RED commits before their respective
fix(*)commits per CONVENTIONS §1.0d-trigies-octies; the build is RED pre-fix (the obsolete ctors and the uncheckedReadAsyncreturns trip the gate underTreatWarningsAsErrors=true) and GREEN post-fix.The CS0162 / CS0809 / CS1574 / NU5017 fixes are build-gate-only — they carry no runtime semantic, so no separate
test(*)commit precedes them; the §1.0d-trigies-octies carve-out for commits whose only behaviour is the build gate applies.Files touched
Source:
adapter/MTConnect.NET-Applications-Adapter/MTConnectAdapterApplication.csadapter/Modules/MTConnect.NET-AdapterModule-MQTT/Module.csagent/MTConnect.NET-Applications-Agents/MTConnectAgentApplication.csagent/Modules/MTConnect.NET-AgentModule-MqttAdapter/Module.cslibraries/MTConnect.NET-HTTP/Ceen/Httpd/HttpServer.cslibraries/MTConnect.NET-HTTP/Ceen/Httpd/LimitedBodyStream.cslibraries/MTConnect.NET-HTTP/Ceen/Httpd/ServerConfig.cslibraries/MTConnect.NET-HTTP/Servers/MTConnectPostResponseHandler.cslibraries/MTConnect.NET-MQTT/Clients/MTConnectMqttExpandedClient.cslibraries/MTConnect.NET-MQTT/MTConnectMqttRelay.cslibraries/MTConnect.NET-SysML/MTConnect.NET-SysML.csprojlibraries/MTConnect.NET-TLS/TlsConfiguration.csTests:
tests/MTConnect.NET-Common-Tests/MTConnect.NET-Common-Tests.csproj(add TLS project reference)tests/MTConnect.NET-Common-Tests/Http/CA2022ShortReadTests.cs(new)tests/MTConnect.NET-Common-Tests/Tls/TlsCertificateLoaderTests.cs(new)CI:
.github/workflows/dotnet.yml— addrelease-packjob.Composes with
ReadRequestBytesbody-corruption fix ships in the discovering PR, not deferred.libraries/MTConnect.NET-HTTP/Ceen/is treated as in-scope; no silent exclusion.test(tls)andtest(http)commits precede their respectivefix(*)commits; pure build-gate fixes use the carve-out.