diff --git a/src/lib/adapters/container-engine.ts b/src/lib/adapters/container-engine.ts index 03419f53942..05d95ec4a93 100644 --- a/src/lib/adapters/container-engine.ts +++ b/src/lib/adapters/container-engine.ts @@ -8,6 +8,7 @@ import { buildSubprocessEnv } from "../subprocess-env"; export type ContainerEngineOperationScope = | "host-doctor" + | "host-local-inference" | "gateway-inspection" | "managed-bootstrap" | "sandbox-lifecycle" diff --git a/src/lib/adapters/podman/index.ts b/src/lib/adapters/podman/index.ts index eba8ee0e1ed..a6639b73be2 100644 --- a/src/lib/adapters/podman/index.ts +++ b/src/lib/adapters/podman/index.ts @@ -15,7 +15,11 @@ import { } from "./socket-authority"; export interface PodmanContainerEngineOptions { - readonly operation: "host-doctor" | "managed-bootstrap" | "sandbox-lifecycle"; + readonly operation: + | "host-doctor" + | "host-local-inference" + | "managed-bootstrap" + | "sandbox-lifecycle"; readonly socketAuthority: PodmanSocketAuthority; readonly executable?: string; readonly capture?: ContainerEngineCommandCapture; diff --git a/src/lib/onboard/runtime-provider/contract.ts b/src/lib/onboard/runtime-provider/contract.ts index 8938b6244ff..f63e429e739 100644 --- a/src/lib/onboard/runtime-provider/contract.ts +++ b/src/lib/onboard/runtime-provider/contract.ts @@ -29,6 +29,7 @@ export type RuntimeProviderMutationOperation = | "workload-cleanup"; export type RuntimeProviderContainerEngineOperation = | "host-doctor" + | "host-local-inference" | "gateway-inspection" | "sandbox-lifecycle" | "workload-cleanup"; diff --git a/src/lib/onboard/runtime-provider/persisted-engine-authority.test.ts b/src/lib/onboard/runtime-provider/persisted-engine-authority.test.ts index 811cff043ec..88c44588c3b 100644 --- a/src/lib/onboard/runtime-provider/persisted-engine-authority.test.ts +++ b/src/lib/onboard/runtime-provider/persisted-engine-authority.test.ts @@ -93,6 +93,25 @@ describe("persisted engine authority", () => { } }); + it("persists a host-local inference engine independently of lifecycle authority", () => { + const store = createFilePersistedEngineAuthorityStore(temporaryRoot()); + const inference = createPersistedEngineAuthority( + "mxc", + engine("host-local-inference"), + BINDING_SHA256, + ); + const lifecycle = createPersistedEngineAuthority( + "mxc", + engine("sandbox-lifecycle"), + BINDING_SHA256, + ); + + expect(store.record(inference)).toEqual(inference); + expect(store.record(lifecycle)).toEqual(lifecycle); + expect(store.load("host-local-inference")).toEqual(inference); + expect(store.load("sandbox-lifecycle")).toEqual(lifecycle); + }); + it.each([ { label: "provider", diff --git a/src/lib/onboard/runtime-provider/persisted-engine-authority.ts b/src/lib/onboard/runtime-provider/persisted-engine-authority.ts index 5dbd9a97026..e4300d84d45 100644 --- a/src/lib/onboard/runtime-provider/persisted-engine-authority.ts +++ b/src/lib/onboard/runtime-provider/persisted-engine-authority.ts @@ -22,6 +22,7 @@ const AUTHORITY_ID = /^[a-z][a-z0-9-]{0,62}:[A-Za-z0-9._:-]{1,255}$/u; const SHA256 = /^[a-f0-9]{64}$/u; const OPERATIONS = new Set([ "host-doctor", + "host-local-inference", "gateway-inspection", "managed-bootstrap", "sandbox-lifecycle", diff --git a/src/lib/onboard/runtime-provider/podman-gpu.test.ts b/src/lib/onboard/runtime-provider/podman-gpu.test.ts new file mode 100644 index 00000000000..9c9b0fef51a --- /dev/null +++ b/src/lib/onboard/runtime-provider/podman-gpu.test.ts @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { describe, expect, it } from "vitest"; + +import { + normalizeNvidiaCdiDevice, + normalizePodmanCdiInventory, + qualifyPodmanGpuAttachments, +} from "./podman-gpu"; + +describe("Podman GPU attachment authority", () => { + it.each([ + ["all", "nvidia.com/gpu=all"], + ["0", "nvidia.com/gpu=0"], + ["1:0", "nvidia.com/gpu=1:0"], + ["GPU-deadbeef", "nvidia.com/gpu=GPU-deadbeef"], + ["nvidia.com/gpu=MIG-deadbeef", "nvidia.com/gpu=MIG-deadbeef"], + [ + "MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0", + "nvidia.com/gpu=MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0", + ], + ])("normalizes %s to canonical NVIDIA CDI identity", (requested, expected) => { + expect(normalizeNvidiaCdiDevice(requested)).toBe(expected); + }); + + it("qualifies only exact devices advertised by the injected endpoint", () => { + const attachments = qualifyPodmanGpuAttachments( + ["nvidia.com/gpu=all", "nvidia.com/gpu=0", "nvidia.com/gpu=GPU-deadbeef"], + ["0", "GPU-deadbeef"], + ); + + expect(attachments).toEqual([ + { kind: "cdi", device: "nvidia.com/gpu=0" }, + { kind: "cdi", device: "nvidia.com/gpu=GPU-deadbeef" }, + ]); + expect(Object.isFrozen(attachments)).toBe(true); + expect(Object.isFrozen(attachments[0])).toBe(true); + }); + + it("fails closed for missing, duplicate, raw, and malformed devices", () => { + expect(() => qualifyPodmanGpuAttachments([], ["all"])).toThrow("does not advertise"); + expect(() => + qualifyPodmanGpuAttachments(["nvidia.com/gpu=0"], ["0", "nvidia.com/gpu=0"]), + ).toThrow("duplicate NVIDIA CDI device"); + expect(() => normalizeNvidiaCdiDevice("/dev/nvidia0")).toThrow("safe NVIDIA CDI name"); + expect(() => normalizePodmanCdiInventory(["all", "nvidia.com/gpu=all"])).toThrow( + "duplicate NVIDIA device", + ); + }); +}); diff --git a/src/lib/onboard/runtime-provider/podman-gpu.ts b/src/lib/onboard/runtime-provider/podman-gpu.ts new file mode 100644 index 00000000000..960c2594776 --- /dev/null +++ b/src/lib/onboard/runtime-provider/podman-gpu.ts @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +const NVIDIA_CDI_PREFIX = "nvidia.com/gpu="; +const CDI_DEVICE_NAME = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,255}$/u; +const LEGACY_MIG_DEVICE_NAME = /^MIG-GPU-[A-Za-z0-9-]+\/[0-9]+\/[0-9]+$/u; + +export interface PodmanGpuAttachment { + readonly kind: "cdi"; + readonly device: string; +} + +/** + * Normalize one NVIDIA CDI device identity without consulting host state. + * Availability is proved separately against the exact Podman endpoint's + * qualified inventory. + */ +export function normalizeNvidiaCdiDevice(requestedDevice: string): string { + const requested = requestedDevice.trim(); + const device = requested.startsWith(NVIDIA_CDI_PREFIX) + ? requested + : `${NVIDIA_CDI_PREFIX}${requested}`; + const name = device.slice(NVIDIA_CDI_PREFIX.length); + if (!CDI_DEVICE_NAME.test(name) && !LEGACY_MIG_DEVICE_NAME.test(name)) { + throw new Error( + "Podman GPU device must be a safe NVIDIA CDI name such as 'all', '0', '1:0', 'GPU-...', or 'MIG-...'.", + ); + } + return device; +} + +export function normalizePodmanCdiInventory(devices: readonly string[]): readonly string[] { + if (!Array.isArray(devices) || devices.length > 256) { + throw new Error("Podman CDI inventory is invalid or exceeds its device limit."); + } + const normalized = devices.map(normalizeNvidiaCdiDevice).sort(); + if (new Set(normalized).size !== normalized.length) { + throw new Error("Podman CDI inventory contains a duplicate NVIDIA device."); + } + return Object.freeze(normalized); +} + +export function qualifyPodmanGpuAttachments( + availableDevices: readonly string[], + requestedDevices: readonly string[] = ["all"], +): readonly PodmanGpuAttachment[] { + const available = new Set(normalizePodmanCdiInventory(availableDevices)); + if (!Array.isArray(requestedDevices) || requestedDevices.length === 0) { + throw new Error("Podman GPU attachment requires at least one NVIDIA CDI device."); + } + const requested = requestedDevices.map(normalizeNvidiaCdiDevice); + if (new Set(requested).size !== requested.length) { + throw new Error("Podman GPU attachment contains a duplicate NVIDIA CDI device."); + } + for (const device of requested) { + if (!available.has(device)) { + throw new Error( + `Rootless Podman does not advertise the requested CDI device '${device}'. Refresh the NVIDIA CDI specification and retry.`, + ); + } + } + return Object.freeze(requested.map((device) => Object.freeze({ kind: "cdi" as const, device }))); +} diff --git a/src/lib/onboard/runtime-provider/podman-inference-args.test.ts b/src/lib/onboard/runtime-provider/podman-inference-args.test.ts new file mode 100644 index 00000000000..100e7cceb91 --- /dev/null +++ b/src/lib/onboard/runtime-provider/podman-inference-args.test.ts @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { describe, expect, it } from "vitest"; + +import { translatePodmanLocalInferenceArgs } from "./podman-inference-args"; + +const CDI_DEVICES = [ + "nvidia.com/gpu=all", + "nvidia.com/gpu=0", + "nvidia.com/gpu=1:0", + "nvidia.com/gpu=2", + "nvidia.com/gpu=GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + "nvidia.com/gpu=MIG-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + "nvidia.com/gpu=MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0", +] as const; + +describe("Podman local inference command translation", () => { + it.each([ + ["all", ["nvidia.com/gpu=all"]], + ["device=0", ["nvidia.com/gpu=0"]], + ["device=1:0", ["nvidia.com/gpu=1:0"]], + [ + "device=GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", + ["nvidia.com/gpu=GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"], + ], + [ + "device=MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0", + ["nvidia.com/gpu=MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0"], + ], + ['"device=0,2"', ["nvidia.com/gpu=0", "nvidia.com/gpu=2"]], + ])("preserves Docker selector %s as exact CDI devices", (selector, devices) => { + const translated = translatePodmanLocalInferenceArgs( + ["run", "--gpus", selector, "image"], + CDI_DEVICES, + ); + expect(translated.filter((value) => value.startsWith("nvidia.com/gpu="))).toEqual(devices); + expect(translated.filter((value) => value === "--device")).toHaveLength(devices.length); + expect(translated).not.toContain("--gpus"); + }); + + it("translates the NIM and vLLM subset without Docker name-filter leakage", () => { + expect( + translatePodmanLocalInferenceArgs( + ["run", "--gpus=all", "--filter", "name=^/nemoclaw-vllm$"], + CDI_DEVICES, + ), + ).toEqual(["run", "--device", "nvidia.com/gpu=all", "--filter", "name=^nemoclaw-vllm$"]); + expect( + translatePodmanLocalInferenceArgs(["run", "--device=nvidia.com/gpu=0", "image"], CDI_DEVICES), + ).toEqual(["run", "--device", "nvidia.com/gpu=0", "image"]); + }); + + it("fails closed instead of dropping unsupported Docker GPU modes", () => { + expect(() => + translatePodmanLocalInferenceArgs( + ["run", "--gpus", "capabilities=compute", "image"], + CDI_DEVICES, + ), + ).toThrow("cannot translate Docker GPU selector"); + expect(() => + translatePodmanLocalInferenceArgs(["run", "--gpus", "device=0,0"], CDI_DEVICES), + ).toThrow("duplicate NVIDIA CDI device"); + expect(() => + translatePodmanLocalInferenceArgs(["run", "--runtime", "nvidia"], CDI_DEVICES), + ).toThrow("refuses Docker's NVIDIA runtime mode"); + expect(() => + translatePodmanLocalInferenceArgs(["run", "--device", "/dev/nvidia0"], CDI_DEVICES), + ).toThrow("refuses raw NVIDIA device paths"); + expect(() => + translatePodmanLocalInferenceArgs(["run", "--gpus", "device=9"], CDI_DEVICES), + ).toThrow("does not advertise"); + }); +}); diff --git a/src/lib/onboard/runtime-provider/podman-inference-args.ts b/src/lib/onboard/runtime-provider/podman-inference-args.ts new file mode 100644 index 00000000000..478a8a7e6a8 --- /dev/null +++ b/src/lib/onboard/runtime-provider/podman-inference-args.ts @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { qualifyPodmanGpuAttachments } from "./podman-gpu"; + +const MAX_ARGUMENTS = 512; +const MAX_ARGUMENT_BYTES = 16 * 1024; + +function exactArgument(value: unknown, index: number): string { + if ( + typeof value !== "string" || + value.includes("\0") || + Buffer.byteLength(value, "utf8") > MAX_ARGUMENT_BYTES + ) { + throw new Error(`Podman local inference argument ${String(index)} is invalid.`); + } + return value; +} + +function stripExactDoubleQuotes(raw: string): string { + const trimmed = raw.trim(); + const startsQuoted = trimmed.startsWith('"'); + const endsQuoted = trimmed.endsWith('"'); + if (startsQuoted !== endsQuoted || (startsQuoted && trimmed.length < 2)) { + throw new Error(`Podman local inference cannot translate Docker GPU selector '${raw}' to CDI.`); + } + return startsQuoted ? trimmed.slice(1, -1) : trimmed; +} + +function translatedGpuDevices(selector: string, availableCdiDevices: readonly string[]): string[] { + const normalized = stripExactDoubleQuotes(selector); + const requested = + normalized === "all" + ? ["all"] + : normalized.startsWith("device=") + ? normalized.slice("device=".length).split(",") + : []; + if (requested.length === 0 || requested.some((device) => device.trim() === "")) { + throw new Error( + `Podman local inference cannot translate Docker GPU selector '${selector}' to CDI.`, + ); + } + return qualifyPodmanGpuAttachments( + availableCdiDevices, + requested.map((device) => device.trim()), + ).map((attachment) => attachment.device); +} + +function appendGpuDevices(target: string[], devices: readonly string[]): void { + for (const device of devices) target.push("--device", device); +} + +/** + * Translate the bounded Docker-compatible argument subset emitted by the + * existing NIM and vLLM launchers. NVIDIA GPU selection becomes exact CDI + * attachment; Docker-only runtime and raw-device modes fail closed. + */ +export function translatePodmanLocalInferenceArgs( + args: readonly string[], + availableCdiDevices: readonly string[], +): readonly string[] { + if (!Array.isArray(args) || args.length > MAX_ARGUMENTS) { + throw new Error("Podman local inference has too many command arguments."); + } + const source = args.map(exactArgument); + const translated: string[] = []; + for (let index = 0; index < source.length; index += 1) { + const value = source[index] ?? ""; + if (value === "--gpus") { + const selector = source[index + 1]; + if (selector === undefined) { + throw new Error("Podman local inference requires a GPU selector value."); + } + appendGpuDevices(translated, translatedGpuDevices(selector, availableCdiDevices)); + index += 1; + continue; + } + if (value.startsWith("--gpus=")) { + appendGpuDevices( + translated, + translatedGpuDevices(value.slice("--gpus=".length), availableCdiDevices), + ); + continue; + } + if ( + (value === "--runtime" && source[index + 1]?.toLowerCase() === "nvidia") || + value.toLowerCase() === "--runtime=nvidia" + ) { + throw new Error( + "Podman local inference refuses Docker's NVIDIA runtime mode; an exact CDI device is required.", + ); + } + if (value === "--device") { + const device = source[index + 1]; + if (device === undefined) { + throw new Error("Podman local inference requires a --device value."); + } + if (/^\/dev\/nvidia/u.test(device)) { + throw new Error( + "Podman local inference refuses raw NVIDIA device paths; an exact CDI device is required.", + ); + } + if (device.startsWith("nvidia.com/gpu=")) { + appendGpuDevices(translated, translatedGpuDevices(`device=${device}`, availableCdiDevices)); + index += 1; + continue; + } + } + if (value.startsWith("--device=/dev/nvidia")) { + throw new Error( + "Podman local inference refuses raw NVIDIA device paths; an exact CDI device is required.", + ); + } + if (value.startsWith("--device=nvidia.com/gpu=")) { + appendGpuDevices( + translated, + translatedGpuDevices(`device=${value.slice("--device=".length)}`, availableCdiDevices), + ); + continue; + } + if (value.startsWith("name=^/") && value.endsWith("$")) { + translated.push(`name=^${value.slice("name=^/".length)}`); + continue; + } + translated.push(value); + } + return Object.freeze(translated); +} diff --git a/src/lib/onboard/runtime-provider/podman-preflight.test.ts b/src/lib/onboard/runtime-provider/podman-preflight.test.ts index 25390bec419..d0579b2575d 100644 --- a/src/lib/onboard/runtime-provider/podman-preflight.test.ts +++ b/src/lib/onboard/runtime-provider/podman-preflight.test.ts @@ -18,6 +18,7 @@ const INFO = JSON.stringify({ cgroupVersion: "v2", networkBackend: "netavark", security: { rootless: true }, + cdi: { devices: ["nvidia.com/gpu=all", "nvidia.com/gpu=0"] }, }, }); @@ -80,6 +81,7 @@ describe("Podman host preflight", () => { expect(qualifyPodmanHost(runtime, { platform: "linux", architecture: "x64" })).toEqual({ providerId: "podman", + authorityId: "test:podman-socket", clientVersion: "5.6.2", serverVersion: "5.6.2", rootless: true, @@ -87,6 +89,7 @@ describe("Podman host preflight", () => { os: "linux", architecture: "amd64", networkBackend: "netavark", + cdiDevices: ["nvidia.com/gpu=0", "nvidia.com/gpu=all"], }); expect(runtime.capture).toHaveBeenCalledWith(["info", "--format", "json"], 15_000); expect(runtime.capture).toHaveBeenCalledWith(["version", "--format", "json"], 10_000); @@ -111,6 +114,43 @@ describe("Podman host preflight", () => { ).toMatchObject({ architecture: "arm64" }); }); + it("combines endpoint-reported and separately qualified CDI inventories", () => { + expect( + qualifyPodmanHost(engine(), { + platform: "linux", + architecture: "x64", + additionalCdiDevices: ["nvidia.com/gpu=GPU-deadbeef"], + }), + ).toMatchObject({ + authorityId: "test:podman-socket", + cdiDevices: ["nvidia.com/gpu=0", "nvidia.com/gpu=GPU-deadbeef", "nvidia.com/gpu=all"], + }); + }); + + it("rejects malformed or duplicate qualified CDI inventory", () => { + expect(() => + qualifyPodmanHost(engine(), { + platform: "linux", + architecture: "x64", + additionalCdiDevices: ["/dev/nvidia0"], + }), + ).toThrow("safe NVIDIA CDI name"); + expect(() => + qualifyPodmanHost(engine(), { + platform: "linux", + architecture: "x64", + additionalCdiDevices: ["all"], + }), + ).toThrow("duplicate NVIDIA device"); + expect(() => + qualifyPodmanHost(engine(), { + platform: "linux", + architecture: "x64", + additionalCdiDevices: ["nvidia.com/gpu=0"], + }), + ).toThrow("duplicate NVIDIA device"); + }); + it("rejects an API service architecture that differs from the host", () => { expect(() => qualifyPodmanHost(engine(), { platform: "linux", architecture: "arm64" })).toThrow( "does not match host 'arm64'", diff --git a/src/lib/onboard/runtime-provider/podman-preflight.ts b/src/lib/onboard/runtime-provider/podman-preflight.ts index 34da16f4f50..b8e3e812635 100644 --- a/src/lib/onboard/runtime-provider/podman-preflight.ts +++ b/src/lib/onboard/runtime-provider/podman-preflight.ts @@ -6,11 +6,14 @@ import type { ContainerEngineCommandResult, } from "../../adapters/container-engine"; import type { RuntimeProviderDoctorCheck } from "./contract"; +import { normalizePodmanCdiInventory } from "./podman-gpu"; export const MINIMUM_PODMAN_VERSION = "5.0.0"; export interface PodmanHostPreflightReceipt { readonly providerId: "podman"; + /** Exact endpoint identity of the operation-scoped engine that produced this receipt. */ + readonly authorityId: string; readonly clientVersion: string; readonly serverVersion: string; readonly rootless: true; @@ -18,11 +21,14 @@ export interface PodmanHostPreflightReceipt { readonly os: "linux"; readonly architecture: "amd64" | "arm64"; readonly networkBackend: string; + readonly cdiDevices: readonly string[]; } export interface PodmanHostPreflightOptions { readonly platform?: NodeJS.Platform; readonly architecture?: NodeJS.Architecture; + /** Additional devices from a separately qualified NVIDIA CDI inventory adapter. */ + readonly additionalCdiDevices?: readonly string[]; } export class PodmanHostPreflightError extends Error { @@ -111,6 +117,23 @@ function normalizeArchitecture(value: string): "amd64" | "arm64" | null { return null; } +function collectNvidiaCdiDevices(value: unknown, devices: string[]): void { + if (typeof value === "string") { + if (value.startsWith("nvidia.com/gpu=")) devices.push(value); + return; + } + if (Array.isArray(value)) { + for (const entry of value) collectNvidiaCdiDevices(entry, devices); + return; + } + const source = record(value); + if (!source) return; + for (const [key, entry] of Object.entries(source)) { + if (key.startsWith("nvidia.com/gpu=")) devices.push(key); + collectNvidiaCdiDevices(entry, devices); + } +} + function hasSubordinateIdMapping(output: string): boolean { return output .trim() @@ -219,8 +242,14 @@ export function qualifyPodmanHost( } requireSubordinateIdMappings(engine); + const cdiDevices: string[] = []; + collectNvidiaCdiDevices(host, cdiDevices); + cdiDevices.push(...(options.additionalCdiDevices ?? [])); + const qualifiedCdiDevices = normalizePodmanCdiInventory(cdiDevices); + return Object.freeze({ providerId: "podman", + authorityId: engine.authorityId, clientVersion, serverVersion, rootless: true, @@ -228,6 +257,7 @@ export function qualifyPodmanHost( os: "linux", architecture: normalizedArchitecture, networkBackend: textField(host, "networkBackend", "NetworkBackend") || "unknown", + cdiDevices: qualifiedCdiDevices, }); } diff --git a/src/lib/onboard/runtime-provider/registry.ts b/src/lib/onboard/runtime-provider/registry.ts index 1d0a31ae6aa..a207877cdb5 100644 --- a/src/lib/onboard/runtime-provider/registry.ts +++ b/src/lib/onboard/runtime-provider/registry.ts @@ -66,6 +66,7 @@ const MUTATION_OPERATIONS = new Set([ ]); const CONTAINER_ENGINE_OPERATIONS = new Set([ "host-doctor", + "host-local-inference", "gateway-inspection", "sandbox-lifecycle", "workload-cleanup", diff --git a/test/runtime-provider-source-shape.test.ts b/test/runtime-provider-source-shape.test.ts index 224dfcc66d5..4b86d0966f3 100644 --- a/test/runtime-provider-source-shape.test.ts +++ b/test/runtime-provider-source-shape.test.ts @@ -167,6 +167,8 @@ describe("runtime provider central source boundary", () => { "src/lib/onboard/runtime-provider/docker.ts", "src/lib/onboard/runtime-provider/persisted-engine-authority.ts", "src/lib/onboard/runtime-provider/persisted-engine-lifecycle.ts", + "src/lib/onboard/runtime-provider/podman-gpu.ts", + "src/lib/onboard/runtime-provider/podman-inference-args.ts", "src/lib/onboard/runtime-provider/podman-lifecycle.ts", "src/lib/onboard/runtime-provider/podman-preflight.ts", "src/lib/onboard/runtime-provider/podman.ts",