From f808c23541dde10555ef93564dfb3fa5ee3698f4 Mon Sep 17 00:00:00 2001 From: Senthil Ravichandran Date: Tue, 4 Aug 2026 09:25:29 -0700 Subject: [PATCH 1/2] feat(onboard): add Windows MXC host qualification --- .../windows-mxc/host-qualification.test.ts | 98 +++++++++++++++++ .../onboard/windows-mxc/host-qualification.ts | 103 ++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 src/lib/onboard/windows-mxc/host-qualification.test.ts create mode 100644 src/lib/onboard/windows-mxc/host-qualification.ts diff --git a/src/lib/onboard/windows-mxc/host-qualification.test.ts b/src/lib/onboard/windows-mxc/host-qualification.test.ts new file mode 100644 index 00000000000..061a4a3d17f --- /dev/null +++ b/src/lib/onboard/windows-mxc/host-qualification.test.ts @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { describe, expect, it } from "vitest"; + +import { + assessWindowsMxcProcessContainerCandidate, + parseWindowsBuild, + WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD, +} from "./host-qualification"; + +describe("native Windows/MXC process_container host qualification", () => { + it("returns a candidate at the exact inactive x64 build floor (#8178)", () => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "win32", + architecture: "x64", + release: `10.0.${WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD}`, + }), + ).toEqual({ + candidate: true, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + platform: "win32", + architecture: "x64", + windowsBuild: WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD, + }); + }); + + it("accepts a newer Windows revision without treating it as the build (#8178)", () => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "win32", + architecture: "x64", + release: "10.0.28000.1836", + }), + ).toMatchObject({ candidate: true, windowsBuild: 28000 }); + }); + + it("rejects WSL and every other non-Windows host (#8178)", () => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "linux", + architecture: "x64", + release: "6.6.87.2-microsoft-standard-WSL2", + }), + ).toMatchObject({ candidate: false, reason: "non-windows-host" }); + }); + + it("fails closed for an architecture outside the initial candidate (#8178)", () => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "win32", + architecture: "arm64", + release: "10.0.28000", + }), + ).toMatchObject({ candidate: false, reason: "unqualified-architecture" }); + }); + + it("fails closed below the process_container candidate build floor (#8178)", () => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "win32", + architecture: "x64", + release: `10.0.${WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD - 1}`, + }), + ).toMatchObject({ + candidate: false, + reason: "windows-build-below-candidate-floor", + }); + }); + + it.each([ + "", + "10", + "10.0", + "10.0.build", + "6.6.87.2-microsoft-standard-WSL2", + ])("fails closed when release %j is not a Windows build form (#8178)", (release) => { + expect( + assessWindowsMxcProcessContainerCandidate({ + platform: "win32", + architecture: "x64", + release, + }), + ).toMatchObject({ candidate: false, reason: "unknown-windows-build" }); + }); +}); + +describe("Windows build parsing", () => { + it.each([ + ["10.0.26100", 26100], + ["10.0.26300.8553", 26300], + [" 10.0.28000.1836 ", 28000], + ])("extracts the build from %s (#8178)", (release, expected) => { + expect(parseWindowsBuild(release)).toBe(expected); + }); +}); diff --git a/src/lib/onboard/windows-mxc/host-qualification.ts b/src/lib/onboard/windows-mxc/host-qualification.ts new file mode 100644 index 00000000000..c2a4e0d2ac8 --- /dev/null +++ b/src/lib/onboard/windows-mxc/host-qualification.ts @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import os from "node:os"; + +export const WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION = 1 as const; +export const WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD = 26100 as const; + +export interface WindowsMxcHostFacts { + readonly platform: NodeJS.Platform; + readonly architecture: string; + readonly release: string; +} + +export type WindowsMxcProcessContainerCandidateResult = + | { + readonly candidate: true; + readonly contractVersion: typeof WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION; + readonly platform: "win32"; + readonly architecture: "x64"; + readonly windowsBuild: number; + } + | { + readonly candidate: false; + readonly contractVersion: typeof WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION; + readonly reason: + | "non-windows-host" + | "unqualified-architecture" + | "unknown-windows-build" + | "windows-build-below-candidate-floor"; + readonly detail: string; + }; + +/** + * Extract the Windows build from the Node.js `os.release()` form + * `..[.]`. + */ +export function parseWindowsBuild(release: string): number | null { + const match = /^\d+\.\d+\.(\d+)(?:\.\d+)?$/.exec(release.trim()); + if (!match) return null; + + const build = Number(match[1]); + return Number.isSafeInteger(build) ? build : null; +} + +/** + * Evaluate the inactive native Windows/MXC `process_container` candidate. + * + * This is a host-facts contract only. A positive result does not select a + * runtime provider or establish a supported Windows compatibility matrix. + */ +export function assessWindowsMxcProcessContainerCandidate( + facts: WindowsMxcHostFacts = { + platform: process.platform, + architecture: process.arch, + release: os.release(), + }, +): WindowsMxcProcessContainerCandidateResult { + if (facts.platform !== "win32") { + return { + candidate: false, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + reason: "non-windows-host", + detail: "Native Windows/MXC requires a Windows host; WSL is not a native Windows host.", + }; + } + + if (facts.architecture !== "x64") { + return { + candidate: false, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + reason: "unqualified-architecture", + detail: "The inactive Windows/MXC process_container candidate currently qualifies x64 only.", + }; + } + + const windowsBuild = parseWindowsBuild(facts.release); + if (windowsBuild === null) { + return { + candidate: false, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + reason: "unknown-windows-build", + detail: "The Windows build could not be determined from the host release.", + }; + } + + if (windowsBuild < WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD) { + return { + candidate: false, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + reason: "windows-build-below-candidate-floor", + detail: `The Windows/MXC process_container candidate requires Windows build ${WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD} or newer.`, + }; + } + + return { + candidate: true, + contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, + platform: "win32", + architecture: "x64", + windowsBuild, + }; +} From 21bb036a717131921e951a0387763345c700ac20 Mon Sep 17 00:00:00 2001 From: Senthil Ravichandran Date: Tue, 4 Aug 2026 09:43:13 -0700 Subject: [PATCH 2/2] fix(onboard): require native Windows architecture --- .../windows-mxc/host-qualification.test.ts | 23 +++++++++---------- .../onboard/windows-mxc/host-qualification.ts | 18 ++++++--------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/lib/onboard/windows-mxc/host-qualification.test.ts b/src/lib/onboard/windows-mxc/host-qualification.test.ts index 061a4a3d17f..e80fb38289d 100644 --- a/src/lib/onboard/windows-mxc/host-qualification.test.ts +++ b/src/lib/onboard/windows-mxc/host-qualification.test.ts @@ -7,7 +7,6 @@ import { assessWindowsMxcProcessContainerCandidate, parseWindowsBuild, WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, - WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD, } from "./host-qualification"; describe("native Windows/MXC process_container host qualification", () => { @@ -15,15 +14,15 @@ describe("native Windows/MXC process_container host qualification", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "win32", - architecture: "x64", - release: `10.0.${WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD}`, + nativeArchitecture: "x64", + release: "10.0.26100", }), ).toEqual({ candidate: true, contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, platform: "win32", - architecture: "x64", - windowsBuild: WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD, + nativeArchitecture: "x64", + windowsBuild: 26100, }); }); @@ -31,7 +30,7 @@ describe("native Windows/MXC process_container host qualification", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "win32", - architecture: "x64", + nativeArchitecture: "x64", release: "10.0.28000.1836", }), ).toMatchObject({ candidate: true, windowsBuild: 28000 }); @@ -41,17 +40,17 @@ describe("native Windows/MXC process_container host qualification", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "linux", - architecture: "x64", + nativeArchitecture: "x64", release: "6.6.87.2-microsoft-standard-WSL2", }), ).toMatchObject({ candidate: false, reason: "non-windows-host" }); }); - it("fails closed for an architecture outside the initial candidate (#8178)", () => { + it("rejects an emulated x64 process on a native ARM64 host (#8178)", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "win32", - architecture: "arm64", + nativeArchitecture: "arm64", release: "10.0.28000", }), ).toMatchObject({ candidate: false, reason: "unqualified-architecture" }); @@ -61,8 +60,8 @@ describe("native Windows/MXC process_container host qualification", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "win32", - architecture: "x64", - release: `10.0.${WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD - 1}`, + nativeArchitecture: "x64", + release: "10.0.26099", }), ).toMatchObject({ candidate: false, @@ -80,7 +79,7 @@ describe("native Windows/MXC process_container host qualification", () => { expect( assessWindowsMxcProcessContainerCandidate({ platform: "win32", - architecture: "x64", + nativeArchitecture: "x64", release, }), ).toMatchObject({ candidate: false, reason: "unknown-windows-build" }); diff --git a/src/lib/onboard/windows-mxc/host-qualification.ts b/src/lib/onboard/windows-mxc/host-qualification.ts index c2a4e0d2ac8..7642b4f4aed 100644 --- a/src/lib/onboard/windows-mxc/host-qualification.ts +++ b/src/lib/onboard/windows-mxc/host-qualification.ts @@ -1,14 +1,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import os from "node:os"; - export const WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION = 1 as const; export const WINDOWS_MXC_PROCESS_CONTAINER_MINIMUM_BUILD = 26100 as const; export interface WindowsMxcHostFacts { readonly platform: NodeJS.Platform; - readonly architecture: string; + readonly nativeArchitecture: string; readonly release: string; } @@ -17,7 +15,7 @@ export type WindowsMxcProcessContainerCandidateResult = readonly candidate: true; readonly contractVersion: typeof WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION; readonly platform: "win32"; - readonly architecture: "x64"; + readonly nativeArchitecture: "x64"; readonly windowsBuild: number; } | { @@ -50,11 +48,7 @@ export function parseWindowsBuild(release: string): number | null { * runtime provider or establish a supported Windows compatibility matrix. */ export function assessWindowsMxcProcessContainerCandidate( - facts: WindowsMxcHostFacts = { - platform: process.platform, - architecture: process.arch, - release: os.release(), - }, + facts: WindowsMxcHostFacts, ): WindowsMxcProcessContainerCandidateResult { if (facts.platform !== "win32") { return { @@ -65,7 +59,9 @@ export function assessWindowsMxcProcessContainerCandidate( }; } - if (facts.architecture !== "x64") { + // `process.arch` identifies the Node.js binary and can report x64 under + // Windows ARM64 emulation. The caller must supply the native host value. + if (facts.nativeArchitecture !== "x64") { return { candidate: false, contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, @@ -97,7 +93,7 @@ export function assessWindowsMxcProcessContainerCandidate( candidate: true, contractVersion: WINDOWS_MXC_PROCESS_CONTAINER_HOST_CONTRACT_VERSION, platform: "win32", - architecture: "x64", + nativeArchitecture: "x64", windowsBuild, }; }