diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 5eb801c3dfc..a93ce1a21e1 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -76,6 +76,11 @@ "test": "restores exact locked posture after root-separated repair and later failure (#7033)", "category": "security" }, + { + "file": "test/muse-glimmer-vllm-image-provenance.test.ts", + "test": "binds the checked-in provenance to the selected runtime", + "category": "security" + }, { "file": "test/muse-glimmer-vllm-image-provenance.test.ts", "test": "rejects %s", diff --git a/docs/inference/set-up-vllm.mdx b/docs/inference/set-up-vllm.mdx index f155ccbb4cd..25b2ffa46f1 100644 --- a/docs/inference/set-up-vllm.mdx +++ b/docs/inference/set-up-vllm.mdx @@ -151,8 +151,9 @@ Managed profiles and model-specific recipes use immutable image digests: - DGX Spark and DGX Station models without a model-specific runtime use the `linux/arm64` digest `sha256:9204569b17ee4c0eff75194b8e6e458479c8aee18953b5ab9cf359fcdac659e2` with a compressed layer size of `9.60 GB` under `nvcr.io/nvidia/vllm:26.05.post1-py3`. N1x uses the same image. -- The DGX Spark Muse Glimmer recipe uses the `linux/arm64` post-merge vLLM nightly digest `sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204` with a compressed layer size of `9.70 GB` under `vllm/vllm-openai`. - The image was built from vLLM commit `ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9`, which contains merged Muse Glimmer support commit `6adad08767583f52eb4d2122111af0bf638ed5e6`. +- The DGX Spark Muse Glimmer recipe uses the `linux/arm64` post-fix vLLM nightly digest `sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965` with a compressed layer size of `9.71 GB` under `vllm/vllm-openai`. + The image was built from vLLM commit `5a4c8d99242e9e069b604d0e9b969e77f7dd501d`, which contains merged Muse Glimmer support commit `6adad08767583f52eb4d2122111af0bf638ed5e6` and the vLLM dependency fix from commit `90984ddbed27a09409506d6d6c0eea87f54b04b5`. + The image includes `huggingface_hub` `1.28.0`, which preserves the pinned model revision when vLLM transfers configuration to the engine process. It pins Hugging Face revision `d35cb79050f419c457611b1cee5c5d15b176f285` for the approximately `25.45 GB` model download. - The DGX Spark Nemotron 3.5 Lightning recipe uses the `linux/arm64` digest `sha256:3af90144a0926e5c5fe46ee16e5201e763dd854538b9d7ce433755f11dadaf78` with a compressed layer size of approximately `12.69 GB` under `vllm/vllm-openai`. It pins Hugging Face revision `0dcd680e5585c791728c83342b311d0a0026dbeb` for the approximately `21.56 GB` model download. diff --git a/internal/security-reviews/muse-glimmer-vllm-image-provenance-v1.json b/internal/security-reviews/muse-glimmer-vllm-image-provenance-v1.json index e28d54fdde4..071bf214c8b 100644 --- a/internal/security-reviews/muse-glimmer-vllm-image-provenance-v1.json +++ b/internal/security-reviews/muse-glimmer-vllm-image-provenance-v1.json @@ -11,51 +11,64 @@ "repository": "vllm/vllm-openai" }, "image": { - "reference": "vllm/vllm-openai@sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204", - "manifestDigest": "sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204", + "reference": "vllm/vllm-openai@sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965", + "manifestDigest": "sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965", "manifestMediaType": "application/vnd.docker.distribution.manifest.v2+json", - "manifestUrl": "https://registry-1.docker.io/v2/vllm/vllm-openai/manifests/sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204", - "configDigest": "sha256:c3f199e54a26d2d7a9a41115cd07ce9d90a6488c5a4e75b17129e1006ce533fd", + "manifestUrl": "https://registry-1.docker.io/v2/vllm/vllm-openai/manifests/sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965", + "configDigest": "sha256:49d2eb65dc2a8dea24e43c27b226f650481ac97d4ba9c567b6e1ca08bc472303", "configMediaType": "application/vnd.docker.container.image.v1+json", - "configSizeBytes": 34762, - "configUrl": "https://registry-1.docker.io/v2/vllm/vllm-openai/blobs/sha256:c3f199e54a26d2d7a9a41115cd07ce9d90a6488c5a4e75b17129e1006ce533fd", + "configSizeBytes": 34738, + "configUrl": "https://registry-1.docker.io/v2/vllm/vllm-openai/blobs/sha256:49d2eb65dc2a8dea24e43c27b226f650481ac97d4ba9c567b6e1ca08bc472303", "layerCount": 32, - "compressedLayerSizeBytes": 9699710136, - "createdAt": "2026-08-14T05:33:50.528328374Z", + "compressedLayerSizeBytes": 9706339423, + "createdAt": "2026-08-19T05:34:00.562836767Z", "platform": { "os": "linux", "architecture": "arm64" } }, "build": { - "sourceRepository": "https://github.com/vllm-project/vllm", - "sourceRevision": "ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "sourceRevisionUrl": "https://github.com/vllm-project/vllm/commit/ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "imageTag": "vllm/vllm-openai:nightly-ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "pipelineId": "019d130e-464e-4ff7-b84b-492992c0c06b", - "pipelineUrl": "https://buildkite.com/vllm/release-v2/builds/5174" + "sourceRevision": "5a4c8d99242e9e069b604d0e9b969e77f7dd501d", + "imageTag": "vllm/vllm-openai:nightly-5a4c8d99242e9e069b604d0e9b969e77f7dd501d", + "pipelineId": "019d130e-464e-4ff7-b84b-492992c0c06b" }, "upstreamSupport": { "museMergeCommit": "6adad08767583f52eb4d2122111af0bf638ed5e6", - "museMergeCommitUrl": "https://github.com/vllm-project/vllm/commit/6adad08767583f52eb4d2122111af0bf638ed5e6", - "comparisonUrl": "https://github.com/vllm-project/vllm/compare/6adad08767583f52eb4d2122111af0bf638ed5e6...ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "relationship": "direct-descendant", - "aheadBy": 1 + "relationship": "descendant", + "aheadBy": 173, + "revisionFixCommit": "90984ddbed27a09409506d6d6c0eea87f54b04b5", + "revisionFixRelationship": "descendant", + "revisionFixAheadBy": 33 }, "reportedLabels": { - "ai.vllm.build.commit": "ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", + "ai.vllm.build.commit": "5a4c8d99242e9e069b604d0e9b969e77f7dd501d", "ai.vllm.build.pipeline": "019d130e-464e-4ff7-b84b-492992c0c06b", - "ai.vllm.build.url": "https://buildkite.com/vllm/release-v2/builds/5174", - "ai.vllm.image.tag": "vllm/vllm-openai:nightly-ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "org.opencontainers.image.revision": "ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9", - "org.opencontainers.image.source": "https://github.com/vllm-project/vllm" + "ai.vllm.image.tag": "vllm/vllm-openai:nightly-5a4c8d99242e9e069b604d0e9b969e77f7dd501d", + "org.opencontainers.image.revision": "5a4c8d99242e9e069b604d0e9b969e77f7dd501d" + }, + "runtimeDependencies": { + "vllmVersion": "0.26.1rc1.dev942+g5a4c8d992", + "huggingfaceHubVersion": "1.28.0", + "sentencepieceVersion": "0.2.2", + "tiktokenVersion": "0.14.0" + }, + "revisionSerialization": { + "model": "Inferact/Muse-Glimmer-30B-NVFP4-W4A4", + "requestedRevision": "d35cb79050f419c457611b1cee5c5d15b176f285", + "resolvedRevisionBeforePickle": "d35cb79050f419c457611b1cee5c5d15b176f285", + "resolvedRevisionAfterPickle": "d35cb79050f419c457611b1cee5c5d15b176f285", + "preserved": true }, "verification": { - "observedAt": "2026-08-14T16:33:50Z", + "observedAt": "2026-08-19T22:53:46Z", "methods": [ "docker-buildx-imagetools-inspect-raw", "docker-image-inspect", - "github-compare-api" + "github-compare-api", + "container-package-imports", + "resolved-revision-pickle-round-trip", + "dgx-spark-cold-cache-startup", + "vllm-openai-api-validation" ], "signedProvenanceAttestation": "not-available" } diff --git a/managed-inference/recipes/vllm.muse-glimmer-30b-nvfp4-w4a4.spark-single.v1.yaml b/managed-inference/recipes/vllm.muse-glimmer-30b-nvfp4-w4a4.spark-single.v1.yaml index 1bd4b5cb3a6..b8a43e91686 100644 --- a/managed-inference/recipes/vllm.muse-glimmer-30b-nvfp4-w4a4.spark-single.v1.yaml +++ b/managed-inference/recipes/vllm.muse-glimmer-30b-nvfp4-w4a4.spark-single.v1.yaml @@ -13,8 +13,8 @@ spec: modelRef: vllm.muse-glimmer-30b-nvfp4-w4a4.v1 runtime: - image: vllm/vllm-openai@sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204 - imageDownloadSizeBytes: 9699710136 + image: vllm/vllm-openai@sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965 + imageDownloadSizeBytes: 9706339423 minimumComputeCapability: 121 minimumGpuMemoryBytes: 25447097878 pullTimeoutSeconds: 3600 diff --git a/src/lib/inference/vllm.test.ts b/src/lib/inference/vllm.test.ts index 10432a4b39f..c126e3cdda7 100644 --- a/src/lib/inference/vllm.test.ts +++ b/src/lib/inference/vllm.test.ts @@ -300,9 +300,9 @@ describe("vLLM profile detection", () => { const resolved = resolveVllmModelRuntime(profile!, muse!); const runtime = resolved.profile; expect(runtime.image).toBe( - "vllm/vllm-openai@sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204", + "vllm/vllm-openai@sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965", ); - expect(runtime.imageDownloadSizeBytes).toBe(9_699_710_136); + expect(runtime.imageDownloadSizeBytes).toBe(9_706_339_423); expect(runtime.modelDownloadSizeBytes).toBe(25_447_097_878); const apiKey = "a".repeat(64); diff --git a/test/managed-inference-catalog-compiler.test.ts b/test/managed-inference-catalog-compiler.test.ts index 56e4b2fa0c0..6ff92d461fb 100644 --- a/test/managed-inference-catalog-compiler.test.ts +++ b/test/managed-inference-catalog-compiler.test.ts @@ -293,7 +293,7 @@ describe("managed inference YAML profile contract", () => { runtime: { architecture: "arm64", image: - "vllm/vllm-openai@sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204", + "vllm/vllm-openai@sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965", }, execution: { materializerRef: "vllm.host-local/v1", diff --git a/test/muse-glimmer-vllm-image-provenance.test.ts b/test/muse-glimmer-vllm-image-provenance.test.ts index dedda9f76b6..1268a625c0a 100644 --- a/test/muse-glimmer-vllm-image-provenance.test.ts +++ b/test/muse-glimmer-vllm-image-provenance.test.ts @@ -35,6 +35,26 @@ const recipe = YAML.parse(readFileSync(RECIPE_PATH, "utf8")) as { }; describe("Muse Glimmer vLLM image provenance", () => { + // source-shape-contract: security -- The checked-in provenance and recipe must resolve to the same reviewed external runtime image and size. + it("binds the checked-in provenance to the selected runtime", () => { + verifyMuseGlimmerVllmImageProvenance(provenance); + + expect(recipe.spec.runtime).toMatchObject({ + architecture: "arm64", + image: MUSE_GLIMMER_VLLM_IMAGE_REFERENCE, + imageDownloadSizeBytes: 9_706_339_423, + }); + + const profile = detectVllmProfile({ platform: "spark", type: "nvidia" }); + const model = VLLM_MODELS.find(({ envValue }) => envValue === "muse-glimmer-30b"); + expect(profile).not.toBeNull(); + expect(model).toBeDefined(); + expect(resolveVllmRuntimeProfile(profile!, model!)).toMatchObject({ + image: MUSE_GLIMMER_VLLM_IMAGE_REFERENCE, + imageDownloadSizeBytes: 9_706_339_423, + }); + }); + // source-shape-contract: security -- Mutating each trust field proves the reviewed provenance record fails closed before a substituted external runtime can be published. it.each([ ["publisher drift", ["publisher", "namespace"], "attacker"], @@ -43,6 +63,12 @@ describe("Muse Glimmer vLLM image provenance", () => { ["source drift", ["build", "sourceRevision"], "0".repeat(40)], ["label drift", ["reportedLabels", "org.opencontainers.image.revision"], "0".repeat(40)], ["support ancestry drift", ["upstreamSupport", "relationship"], "unverified"], + ["runtime dependency drift", ["runtimeDependencies", "huggingfaceHubVersion"], "1.27.0"], + [ + "revision serialization drift", + ["revisionSerialization", "resolvedRevisionAfterPickle"], + "main", + ], ] as const)("rejects %s", (_name, pathParts, replacement) => { const changed = structuredClone(provenance) as JsonRecord; let target = changed; diff --git a/test/support/muse-glimmer-vllm-image-provenance-test-support.ts b/test/support/muse-glimmer-vllm-image-provenance-test-support.ts index fc1ff63c35e..34ec6ee7c9d 100644 --- a/test/support/muse-glimmer-vllm-image-provenance-test-support.ts +++ b/test/support/muse-glimmer-vllm-image-provenance-test-support.ts @@ -3,13 +3,14 @@ import assert from "node:assert/strict"; -const MANIFEST_DIGEST = "sha256:677afd5bf3b4bb9881f91e107af7098f8410726b4c05b25cb4a815900b398204"; +const MANIFEST_DIGEST = "sha256:b0e84e5f2b00a7268e4fdda332790ebd4bfb166b64757e166914753afaeee965"; export const MUSE_GLIMMER_VLLM_IMAGE_REFERENCE = `vllm/vllm-openai@${MANIFEST_DIGEST}`; -const CONFIG_DIGEST = "sha256:c3f199e54a26d2d7a9a41115cd07ce9d90a6488c5a4e75b17129e1006ce533fd"; -const SOURCE_REVISION = "ac7509e2b1db40fec2f03dde1ed4e9dfdc2338c9"; +const CONFIG_DIGEST = "sha256:49d2eb65dc2a8dea24e43c27b226f650481ac97d4ba9c567b6e1ca08bc472303"; +const SOURCE_REVISION = "5a4c8d99242e9e069b604d0e9b969e77f7dd501d"; const MUSE_MERGE_COMMIT = "6adad08767583f52eb4d2122111af0bf638ed5e6"; +const REVISION_FIX_COMMIT = "90984ddbed27a09409506d6d6c0eea87f54b04b5"; +const MODEL_REVISION = "d35cb79050f419c457611b1cee5c5d15b176f285"; const PIPELINE_ID = "019d130e-464e-4ff7-b84b-492992c0c06b"; -const PIPELINE_URL = "https://buildkite.com/vllm/release-v2/builds/5174"; const EXPECTED_PROVENANCE = { schemaVersion: 1, @@ -30,42 +31,59 @@ const EXPECTED_PROVENANCE = { manifestUrl: `https://registry-1.docker.io/v2/vllm/vllm-openai/manifests/${MANIFEST_DIGEST}`, configDigest: CONFIG_DIGEST, configMediaType: "application/vnd.docker.container.image.v1+json", - configSizeBytes: 34_762, + configSizeBytes: 34_738, configUrl: `https://registry-1.docker.io/v2/vllm/vllm-openai/blobs/${CONFIG_DIGEST}`, layerCount: 32, - compressedLayerSizeBytes: 9_699_710_136, - createdAt: "2026-08-14T05:33:50.528328374Z", + compressedLayerSizeBytes: 9_706_339_423, + createdAt: "2026-08-19T05:34:00.562836767Z", platform: { os: "linux", architecture: "arm64", }, }, build: { - sourceRepository: "https://github.com/vllm-project/vllm", sourceRevision: SOURCE_REVISION, - sourceRevisionUrl: `https://github.com/vllm-project/vllm/commit/${SOURCE_REVISION}`, imageTag: `vllm/vllm-openai:nightly-${SOURCE_REVISION}`, pipelineId: PIPELINE_ID, - pipelineUrl: PIPELINE_URL, }, upstreamSupport: { museMergeCommit: MUSE_MERGE_COMMIT, - museMergeCommitUrl: `https://github.com/vllm-project/vllm/commit/${MUSE_MERGE_COMMIT}`, - comparisonUrl: `https://github.com/vllm-project/vllm/compare/${MUSE_MERGE_COMMIT}...${SOURCE_REVISION}`, - relationship: "direct-descendant", - aheadBy: 1, + relationship: "descendant", + aheadBy: 173, + revisionFixCommit: REVISION_FIX_COMMIT, + revisionFixRelationship: "descendant", + revisionFixAheadBy: 33, }, reportedLabels: { "ai.vllm.build.commit": SOURCE_REVISION, "ai.vllm.build.pipeline": PIPELINE_ID, - "ai.vllm.build.url": PIPELINE_URL, "ai.vllm.image.tag": `vllm/vllm-openai:nightly-${SOURCE_REVISION}`, "org.opencontainers.image.revision": SOURCE_REVISION, - "org.opencontainers.image.source": "https://github.com/vllm-project/vllm", + }, + runtimeDependencies: { + vllmVersion: "0.26.1rc1.dev942+g5a4c8d992", + huggingfaceHubVersion: "1.28.0", + sentencepieceVersion: "0.2.2", + tiktokenVersion: "0.14.0", + }, + revisionSerialization: { + model: "Inferact/Muse-Glimmer-30B-NVFP4-W4A4", + requestedRevision: MODEL_REVISION, + resolvedRevisionBeforePickle: MODEL_REVISION, + resolvedRevisionAfterPickle: MODEL_REVISION, + preserved: true, }, verification: { - observedAt: "2026-08-14T16:33:50Z", - methods: ["docker-buildx-imagetools-inspect-raw", "docker-image-inspect", "github-compare-api"], + observedAt: "2026-08-19T22:53:46Z", + methods: [ + "docker-buildx-imagetools-inspect-raw", + "docker-image-inspect", + "github-compare-api", + "container-package-imports", + "resolved-revision-pickle-round-trip", + "dgx-spark-cold-cache-startup", + "vllm-openai-api-validation", + ], signedProvenanceAttestation: "not-available", }, } as const;