diff --git a/.github/actions/ci-build-typecheck/action.yaml b/.github/actions/ci-build-typecheck/action.yaml index 869125ed57f..a696c771231 100644 --- a/.github/actions/ci-build-typecheck/action.yaml +++ b/.github/actions/ci-build-typecheck/action.yaml @@ -17,9 +17,9 @@ runs: shell: bash run: npm run typecheck:cli - - name: Typecheck plugin + - name: Typecheck plugin tests shell: bash - run: npm --prefix nemoclaw run typecheck + run: npm --prefix nemoclaw exec -- tsc --noEmit -p nemoclaw/tsconfig.test.json - name: Typecheck JavaScript config shell: bash diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 4eae5803683..0edada8117e 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -176,6 +176,11 @@ "test": "provides the package token only to trusted main dependency installation", "category": "security" }, + { + "file": "test/automation/pull-requests/pr-workflow-contract.test.ts", + "test": "keeps %s plugin test typechecking after the trusted production build", + "category": "security" + }, { "file": "test/automation/pull-requests/pr-workflow-contract.test.ts", "test": "passes only the base-packaged SDK archive to pull request dependency jobs", diff --git a/src/lib/onboard/wsl-docker-desktop-gpu.test.ts b/src/lib/onboard/wsl-docker-desktop-gpu.test.ts index 99f31552fac..5204d06b4e2 100644 --- a/src/lib/onboard/wsl-docker-desktop-gpu.test.ts +++ b/src/lib/onboard/wsl-docker-desktop-gpu.test.ts @@ -173,6 +173,7 @@ describe("createArm64ContainerGpuProver (#4565)", () => { platform: "linux", arch: "arm64", env: {}, + resolveRuntimeProvider: () => proofProvider("docker"), runProof, log: () => undefined, }); @@ -195,6 +196,7 @@ describe("createArm64ContainerGpuProver (#4565)", () => { platform: "linux", arch: "arm64", env: {}, + resolveRuntimeProvider: () => proofProvider("docker"), runProof, log: () => undefined, }); @@ -709,6 +711,7 @@ describe("createArm64ContainerGpuProver (#4565)", () => { platform: "linux", arch: "arm64", env: {}, + resolveRuntimeProvider: () => proofProvider("docker"), runProof: () => passingProof, log: (message) => logs.push(message), }); @@ -743,6 +746,7 @@ describe("createArm64ContainerGpuProver (#4565)", () => { const prover = createArm64ContainerGpuProver({ platform: "linux", arch: "arm64", + resolveRuntimeProvider: () => proofProvider("docker"), runProof: () => failing, log: () => undefined, }); @@ -761,6 +765,7 @@ describe("createArm64ContainerGpuProver (#4565)", () => { const prover = createArm64ContainerGpuProver({ platform: "linux", arch: "arm64", + resolveRuntimeProvider: () => proofProvider("docker"), runProof: () => execFormatFailure, log: (message) => logs.push(message), }); diff --git a/test/automation/pull-requests/pr-workflow-contract.test.ts b/test/automation/pull-requests/pr-workflow-contract.test.ts index 0214da80c81..a738db164da 100644 --- a/test/automation/pull-requests/pr-workflow-contract.test.ts +++ b/test/automation/pull-requests/pr-workflow-contract.test.ts @@ -571,6 +571,22 @@ describe("pull request and main workflow contracts", () => { ); }); + // source-shape-contract: security -- The trusted split must retain test-config coverage after compiling candidate production code + it.each([ + ["pull request", prWorkflow], + ["main", mainWorkflow], + ] as const)( + "keeps %s plugin test typechecking after the trusted production build", + (_name, workflow) => { + expect([workflow.jobs["build-typecheck"].needs].flat()).toContain("compile-artifacts"); + expect(requiredStep(sharedActions.buildTypecheck, "Typecheck plugin tests").run).toBe( + "npm --prefix nemoclaw exec -- tsc --noEmit -p nemoclaw/tsconfig.test.json", + ); + expect(stepRuns(sharedActions.buildTypecheck)).not.toContain( + "npm --prefix nemoclaw run typecheck", + ); + }, + ); it.each([ [ "CLI shards", diff --git a/test/credentials/credential-rotation.test.ts b/test/credentials/credential-rotation.test.ts index 1344b88f019..e76830e794a 100644 --- a/test/credentials/credential-rotation.test.ts +++ b/test/credentials/credential-rotation.test.ts @@ -1,71 +1,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import { createRequire } from "node:module"; -import { beforeEach, describe, expect, it, vi } from "vitest"; - -const require = createRequire(import.meta.url); - -type ModuleProperty = string | number | boolean | Function | object | null | undefined; -type ModuleRecord = { [key: string]: ModuleProperty }; - -type MessagingProvider = { - name: string; - envKey: string; - token: string | null; -}; - -type CredentialRotationInternals = { - hashCredential: (value: string | null | undefined) => string | null; - detectMessagingCredentialRotation: ( - sandboxName: string, - providers: MessagingProvider[], - ) => { changed: boolean; changedProviders: string[] }; -}; - -function isObjectRecord(value: unknown): value is ModuleRecord { - return typeof value === "object" && value !== null && !Array.isArray(value); -} - -function isCredentialRotationInternals(value: unknown): value is CredentialRotationInternals { - return ( - isObjectRecord(value) && - typeof value.hashCredential === "function" && - typeof value.detectMessagingCredentialRotation === "function" - ); -} - -function isRegistryModule(value: unknown): value is typeof import("../../src/lib/state/registry.js") { - return isObjectRecord(value) && typeof value.getSandbox === "function"; -} - -function loadCredentialRotationInternals(): CredentialRotationInternals { - const loaded: unknown = require("../../src/lib/onboard.js"); - if (!isCredentialRotationInternals(loaded)) { - throw new Error("Expected onboard internals to expose credential rotation helpers"); - } - return loaded; -} - -function loadRegistryModule(): typeof import("../../src/lib/state/registry.js") { - const loaded: unknown = require("../../src/lib/state/registry.js"); - if (!isRegistryModule(loaded)) { - throw new Error("Expected registry module to expose getSandbox"); - } - return loaded; -} +import { describe, expect, it, vi } from "vitest"; +import { detectMessagingCredentialRotation } from "../../src/lib/onboard/messaging-credentials"; +import { hashCredential } from "../../src/lib/security/credential-hash"; +import * as registry from "../../src/lib/state/registry"; describe("credential rotation detection", () => { - let hashCredential: CredentialRotationInternals["hashCredential"]; - let detectMessagingCredentialRotation: CredentialRotationInternals["detectMessagingCredentialRotation"]; - let registry: typeof import("../../src/lib/state/registry.js"); - - beforeEach(() => { - // Fresh imports to avoid cross-test contamination - ({ hashCredential, detectMessagingCredentialRotation } = loadCredentialRotationInternals()); - registry = loadRegistryModule(); - }); - function hashCredentialOrThrow(value: string): string { const hash = hashCredential(value); expect(hash).not.toBeNull();