Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ci/source-shape-test-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@
"test": "accepts the prospective dev MUSL sandbox template with its trusted digest",
"category": "security"
},
{
"file": "test/install/installer-supervisor-manifest-trust.test.ts",
"test": "accepts the prospective shared gateway state resolver template (#10544)",
"category": "security"
},
{
"file": "test/mcp/mcp-tool-discovery-image-contract.test.ts",
"test": "pins the reviewed image runtime artifacts exactly",
Expand Down
29 changes: 24 additions & 5 deletions scripts/checks/extract-installer-pins.mts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ const MAX_INSTALLER_INPUT_BYTES = 1024 * 1024;
// operational template. Its exact prospective digests are repeated only for
// release records that can select that same template; dependent installer
// hash tests execute the corresponding release and qualification fixtures.
// The shared gateway state resolver likewise changes the version-independent
// supervisor runtime template. Its prospective digest is repeated only for
// release records with a supervisor identity, and its trust test constructs
// the exact follow-up template before the runtime change can land.
const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
{
brevTemplateSha256: ["c0a4ddf25a02a9fe02b2df53a60942ea887610f04d4ce16a121b6e79a5aeff1a"],
Expand Down Expand Up @@ -126,7 +130,10 @@ const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
image: "ghcr.io/nvidia/openshell/supervisor",
manifestDigest: "sha256:80ed9cda5bf672fefdb9dcd4604b40a8b09c0891b6eb9d03e10227c7e3dfb49d",
required: true,
runtimeTemplateSha256: ["c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068"],
runtimeTemplateSha256: [
"c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068",
"abfc1337284d437e71e47945936af7ef0bc6f28ac2495e12fac41894eb24ce3c",
],
},
version: "0.0.72",
},
Expand Down Expand Up @@ -239,7 +246,10 @@ const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
image: "ghcr.io/nvidia/openshell/supervisor",
manifestDigest: "sha256:ea3632b6e9528e2309103af5b6949606fcdc83ca1f69e8db81482a25bea84bb6",
required: true,
runtimeTemplateSha256: ["c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068"],
runtimeTemplateSha256: [
"c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068",
"abfc1337284d437e71e47945936af7ef0bc6f28ac2495e12fac41894eb24ce3c",
],
},
version: "0.0.99",
},
Expand Down Expand Up @@ -286,7 +296,10 @@ const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
image: "ghcr.io/nvidia/openshell/supervisor",
manifestDigest: "sha256:b58be5e40c788977ffa0e8305a8cad9c656efdf1a3fe182582a00ca870bb0edb",
required: true,
runtimeTemplateSha256: ["c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068"],
runtimeTemplateSha256: [
"c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068",
"abfc1337284d437e71e47945936af7ef0bc6f28ac2495e12fac41894eb24ce3c",
],
},
version: "0.0.101",
},
Expand Down Expand Up @@ -330,7 +343,10 @@ const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
image: "ghcr.io/nvidia/openshell/supervisor",
manifestDigest: "sha256:96228f110362ffd415bb12d3b7f584063c3c52c0c93f3ccf59faada1dc2dd5d3",
required: false,
runtimeTemplateSha256: ["c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068"],
runtimeTemplateSha256: [
"c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068",
"abfc1337284d437e71e47945936af7ef0bc6f28ac2495e12fac41894eb24ce3c",
],
},
version: "0.0.103",
},
Expand Down Expand Up @@ -391,7 +407,10 @@ const TRUSTED_OPENSHELL_RELEASES: readonly OpenShellReleaseTrust[] = [
image: "ghcr.io/nvidia/openshell/supervisor",
manifestDigest: "sha256:722f44669722961b7f432b0b81de25b91a58f34a61d6403bef967acaf2b3af01",
required: false,
runtimeTemplateSha256: ["c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068"],
runtimeTemplateSha256: [
"c1922eaa4f73c1a05aa8bccf50fc40208d7f71db0e6c110dcd09d0372d1aa068",
"abfc1337284d437e71e47945936af7ef0bc6f28ac2495e12fac41894eb24ce3c",
],
},
version: "0.0.106",
},
Expand Down
30 changes: 30 additions & 0 deletions test/install/installer-supervisor-manifest-trust.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,27 @@ function selectOpenShellV00103(): {
return { blueprint, brevInstaller, installer, supervisorRuntime };
}

function selectSharedGatewayStateResolver(source: string): string {
const localResolver = ` function getDockerDriverGatewayStateDir(): string {
const configured = process.env.NEMOCLAW_OPENSHELL_GATEWAY_STATE_DIR;
if (configured && configured.trim()) return path.resolve(configured.trim());
const dir = gatewayBinding.resolveGatewayStateDirName(currentGatewayPort());
return path.join(os.homedir(), ".local", "state", "nemoclaw", dir);
}`;
const sharedResolver = ` function getDockerDriverGatewayStateDir(): string {
return gatewayBinding.resolveGatewayStateDirForPort({
configured: process.env.NEMOCLAW_OPENSHELL_GATEWAY_STATE_DIR,
home: os.homedir(),
port: currentGatewayPort(),
});
}`;
const prospective = source.includes(sharedResolver)
? source
: source.replace(localResolver, sharedResolver);
expect(prospective, "shared gateway state resolver").toContain(sharedResolver);
return prospective;
}

type RunOptions = {
candidateParserBypass?: boolean;
selectV00103?: boolean;
Expand Down Expand Up @@ -206,6 +227,15 @@ describe("OpenShell supervisor manifest trust", () => {
expect(result.status, result.stderr).toBe(0);
});

// source-shape-contract: security -- Exact prospective supervisor runtime bytes must be base-authorized before trusted CI can admit the dependent state-resolver change
it("accepts the prospective shared gateway state resolver template (#10544)", () => {
const prospective = selectSharedGatewayStateResolver(SUPERVISOR_RUNTIME_TEMPLATE);
expect(prospective).toContain("gatewayBinding.resolveGatewayStateDirForPort({");
const result = runParser({ transformSupervisor: () => prospective });

expect(result.status, result.stderr).toBe(0);
});

it.each([["0.0.103", V00103_SUPERVISOR_MANIFEST_DIGEST]] as const)(
"accepts the base-trusted OpenShell %s supervisor identity before version selection (#8893)",
(version, digest) => {
Expand Down
Loading