From 6b2b00bc1a96ef4ca248e1b3434b914b7cc419bc Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 10:57:55 -0700 Subject: [PATCH 1/6] test: remove source-shape assertions --- ci/source-shape-test-budget.json | 510 +---------------- .../openclaw-2026.6.10-dependency-review.md | 2 +- .../mcp-bridge-input-validation.test.ts | 48 -- src/lib/agent/base-image-hermes.test.ts | 112 ---- .../agent/state-directory-contract.test.ts | 19 - .../compatible-endpoint-gateway-route.test.ts | 19 - .../onboard/managed-startup-profile.test.ts | 51 -- test/agent-variant-docs.test.ts | 270 --------- test/code-change-considerations.test.ts | 36 -- test/corporate-ca-build-tls-anchor.test.ts | 257 --------- test/e2e-fixture-dependency-review.test.ts | 30 - test/e2e/mock-parity.json | 3 +- ...mage-publication-workflow-boundary.test.ts | 21 - .../dockerhub-auth-workflow-boundary.test.ts | 55 -- test/e2e/support/e2e-expected-state.test.ts | 115 ---- ...-host-dependency-workflow-boundary.test.ts | 26 - .../support/e2e-live-project-config.test.ts | 58 -- .../e2e-live-registry-discovery.test.ts | 11 - .../e2e-live-skip-name-contract.test.ts | 20 - test/e2e/support/e2e-manifests.test.ts | 13 - test/e2e/support/e2e-matrix.test.ts | 24 - .../support/e2e-semantic-phase-check.test.ts | 17 - .../support/podman-cpu-proof-workflow.test.ts | 102 ---- .../support/same-commit-reliability.test.ts | 29 - test/fetch-guard-patch-regression.test.ts | 28 - test/hermes-final-image-layout.test.ts | 319 ----------- test/hosted-runner-recovery-workflow.test.ts | 9 - test/inference-options-docs.test.ts | 536 ------------------ ...-merged-pr-release-target-workflow.test.ts | 46 -- test/mcp-openshell-workflow.test.ts | 16 - .../mcp-tool-discovery-image-contract.test.ts | 155 ----- test/messaging-image-env-contract.test.ts | 38 -- ...muse-glimmer-vllm-image-provenance.test.ts | 20 - .../onboard-performance-config-schema.test.ts | 331 ----------- test/openclaw-dependency-review.test.ts | 19 - test/openclaw-final-image-layout.test.ts | 223 -------- test/openclaw-lifecycle-policy.test.ts | 166 ------ test/openclaw-locked-install.test.ts | 50 -- ...openshell-0.0.101-migration-review.test.ts | 69 --- .../openshell-0.0.99-migration-review.test.ts | 56 -- test/pi-candidate-runtime-artifacts.test.ts | 203 ------- test/platform-vitest-main-workflow.test.ts | 212 ------- test/plugin-vitest-project.test.ts | 76 --- ...dvisor-openshell-workflow-boundary.test.ts | 290 ---------- test/release-latest-tag-workflow.test.ts | 8 - test/runner.test.ts | 21 - test/runtime-provider-source-shape.test.ts | 399 ------------- test/source-architecture.test.ts | 27 - test/starter-prompt-docs.test.ts | 37 -- test/validate-blueprint.test.ts | 26 - test/vitest-coverage-thresholds.test.ts | 61 -- test/vitest-developer-feedback.test.ts | 23 +- test/vitest-state-isolation.test.ts | 78 --- test/vitest-temp-root.test.ts | 32 -- test/vitest-watch-triggers.test.ts | 6 - 55 files changed, 15 insertions(+), 5413 deletions(-) delete mode 100644 test/corporate-ca-build-tls-anchor.test.ts delete mode 100644 test/inference-options-docs.test.ts delete mode 100644 test/openclaw-lifecycle-policy.test.ts delete mode 100644 test/runtime-provider-source-shape.test.ts delete mode 100644 test/vitest-state-isolation.test.ts diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 8349bfac4ed..3c855635cbb 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -1,36 +1,6 @@ { "maxSourceShapeCases": 0, "sourceShapeContractExceptions": [ - { - "file": "src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts", - "test": "rejects host subprocess control and allowlist names as MCP credentials", - "category": "compatibility" - }, - { - "file": "src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts", - "test": "rejects OpenShell child-environment compatibility keys as MCP credentials", - "category": "compatibility" - }, - { - "file": "src/lib/agent/base-image-hermes.test.ts", - "test": "requires the pinned Hermes base image and checks installed dependency versions after messaging package installation (#8328)", - "category": "security" - }, - { - "file": "src/lib/agent/state-directory-contract.test.ts", - "test": "keeps generated image plans equal to their AgentDefinition projections (#8006)", - "category": "security" - }, - { - "file": "src/lib/onboard/managed-startup-profile.test.ts", - "test": "classifies every stock Docker ARG as startup-affordance or deliberate exclusion", - "category": "compatibility" - }, - { - "file": "src/lib/onboard/managed-startup-profile.test.ts", - "test": "classifies every centralized runtime input as profile intent or an explicit deferral", - "category": "compatibility" - }, { "file": "src/lib/readiness/host.test.ts", "test": "bounds and redacts successful probe text before schema validation", @@ -42,48 +12,13 @@ "category": "compatibility" }, { - "file": "src/lib/onboard/inference-providers/compatible-endpoint-gateway-route.test.ts", - "test": "matches the bundled local-inference host-gateway ports (#5744)", - "category": "compatibility" - }, - { - "file": "test/agent-variant-docs.test.ts", - "test": "keeps the OpenClaw workspace inventory aligned with seeded runtime templates", - "category": "compatibility" - }, - { - "file": "test/code-change-considerations.test.ts", - "test": "keeps the stage-neutral questions in one concise owner", - "category": "compatibility" - }, - { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "declares exactly one corporate CA build arg so onboard patching stays unambiguous", - "category": "security" - }, - { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "uses conditional Node and curl trust in every final-stage registry step", - "category": "security" - }, - { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "accepts the corporate CA build arg in the DCode base image before HTTPS fetches", - "category": "security" - }, - { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "decodes the corporate CA again in the DCode final image", - "category": "security" - }, - { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "copies the reviewed DCode discovery runtime without registry access", + "file": "src/lib/state/sandbox-backup-sanitization.test.ts", + "test": "leaves an installed package manifest that names a credential-shaped dependency", "category": "security" }, { - "file": "test/corporate-ca-build-tls-anchor.test.ts", - "test": "uses the corporate CA conditionally for all Hermes registry remediations", + "file": "src/lib/state/sandbox-backup-sanitization.test.ts", + "test": "returns a credential-free JSON manifest byte for byte", "category": "security" }, { @@ -91,111 +26,16 @@ "test": "rejects a mutated checked-in security inventory instruction (#6024)", "category": "security" }, - { - "file": "test/e2e-fixture-dependency-review.test.ts", - "test": "keeps installed fixture dependencies on exact versions", - "category": "security" - }, { "file": "test/e2e/live/hermes-e2e.test.ts", "test": "hermes-e2e: install.sh onboards Hermes and proves health plus live inference", "category": "security" }, - { - "file": "test/e2e/support/base-image-publication-workflow-boundary.test.ts", - "test": "retains immutable base contracts for later qualification (#9049)", - "category": "security" - }, - { - "file": "test/e2e/support/dockerhub-auth-workflow-boundary.test.ts", - "test": "binds the cleanup action and helper content to the pinned commit", - "category": "security" - }, - { - "file": "test/e2e/support/dockerhub-auth-workflow-boundary.test.ts", - "test": "binds the composite action and helper to their immutable reviewed revision (#6961)", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-host-dependency-workflow-boundary.test.ts", - "test": "binds the host-dependency action and helper to their immutable reviewed revision (#6961)", - "category": "security" - }, - { - "file": "test/e2e/support/same-commit-reliability.test.ts", - "test": "locks the reporter to canonical source and trusted controller identities (#9168)", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "compiles absence probes for every preflight failure contract", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "compiles fail-closed absence probes for targets that forbid runtime side effects", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "compiles gateway-health and host-preservation probes for every post-reboot recovery target", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "indexes every registered state by its unique id", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "keeps policy-selection failures limited to the installed CLI", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "omits host gateway probes for targets whose loaded agent runtime is terminal", - "category": "compatibility" - }, { "file": "test/e2e/support/e2e-expected-state.test.ts", "test": "rejects an unknown state with an actionable inventory", "category": "compatibility" }, - { - "file": "test/e2e/support/e2e-expected-state.test.ts", - "test": "resolves every state id consumed by the typed target registry", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-live-project-config.test.ts", - "test": "keeps the drift-preflight bypass out of live projects (#6692)", - "category": "security" - }, - { - "file": "test/e2e/support/e2e-live-registry-discovery.test.ts", - "test": "classifies every shipped target as supported or with a concrete reason", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-live-skip-name-contract.test.ts", - "test": "matches the workflow's exact `-t \"^${TARGET_ID}$\"` regex for every target", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-live-skip-name-contract.test.ts", - "test": "registers every target under a name equal to its id", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-manifests.test.ts", - "test": "resolves every typed target manifest path to a validated manifest", - "category": "compatibility" - }, - { - "file": "test/e2e/support/e2e-matrix.test.ts", - "test": "builds the default live matrix from every fixture-supported target", - "category": "compatibility" - }, { "file": "test/e2e/support/e2e-registry.test.ts", "test": "CLI should emit multiple selected live matrix entries", @@ -206,11 +46,6 @@ "test": "should return actionable unknown target error", "category": "compatibility" }, - { - "file": "test/e2e/support/e2e-semantic-phase-check.test.ts", - "test": "builds the policy boundary before semantic collection and CLI compilation", - "category": "compatibility" - }, { "file": "test/e2e/support/larger-runner-routing-workflow-boundary.test.ts", "test": "keeps every candidate on standard runners when $name (#7145)", @@ -227,38 +62,8 @@ "category": "security" }, { - "file": "test/e2e/support/podman-cpu-proof-workflow.test.ts", - "test": "runs as a credential-free PR workflow bound to the commit under review", - "category": "security" - }, - { - "file": "test/fetch-guard-patch-regression.test.ts", - "test": "requires classifier review and integrity evidence when the OpenClaw build pin changes", - "category": "security" - }, - { - "file": "test/hermes-final-image-layout.test.ts", - "test": "uses grouped legacy-compatible payload layers at their cache boundaries (#7611)", - "category": "compatibility" - }, - { - "file": "test/hermes-final-image-layout.test.ts", - "test": "keeps security entrypoint hashes synchronized with the copied files", - "category": "security" - }, - { - "file": "test/hermes-final-image-layout.test.ts", - "test": "verifies CLI adapter integrity before executing its validator", - "category": "security" - }, - { - "file": "test/openclaw-final-image-layout.test.ts", - "test": "uses grouped legacy-compatible payload layers at their cache boundaries (#7611)", - "category": "compatibility" - }, - { - "file": "test/hermes-runtime-config-guard-topology.test.ts", - "test": "restores exact locked posture after root-separated repair and later failure (#7033)", + "file": "test/growth-guardrails-workflow-boundary.test.ts", + "test": "flags %s", "category": "security" }, { @@ -267,28 +72,8 @@ "category": "security" }, { - "file": "test/hosted-runner-recovery-workflow.test.ts", - "test": "locks recovery to the platform workflow name (#7140)", - "category": "security" - }, - { - "file": "test/inference-options-docs.test.ts", - "test": "keeps a per-model task-fit comparison table for curated onboarding models", - "category": "compatibility" - }, - { - "file": "test/label-merged-pr-release-target-workflow.test.ts", - "test": "keeps fork-safe labeling inside the trusted metadata boundary", - "category": "security" - }, - { - "file": "test/messaging-image-env-contract.test.ts", - "test": "%s keeps the full plan in build processes but not final runtime environments (#5896)", - "category": "security" - }, - { - "file": "test/muse-glimmer-vllm-image-provenance.test.ts", - "test": "binds the selected runtime to its reviewed publisher, manifest, platform, and source", + "file": "test/hermes-runtime-config-guard-topology.test.ts", + "test": "restores exact locked posture after root-separated repair and later failure (#7033)", "category": "security" }, { @@ -297,55 +82,10 @@ "category": "security" }, { - "file": "test/mcp-tool-discovery-image-contract.test.ts", - "test": "pins reviewed packages and audits their lock outside image builds (#8253)", - "category": "security" - }, - { - "file": "test/mcp-tool-discovery-image-contract.test.ts", - "test": "pins dependency-materialization RUN cache identity", - "category": "compatibility" - }, - { - "file": "test/mcp-openshell-workflow.test.ts", - "test": "keeps the setup docs aligned with the stable default", - "category": "compatibility" - }, - { - "file": "test/openshell-0.0.101-migration-review.test.ts", - "test": "binds the newly generated credential manifest to reviewed source identities (#8599)", - "category": "security" - }, - { - "file": "test/openshell-0.0.99-migration-review.test.ts", - "test": "associates every reviewed release identity with the 0.0.99 manifest (#8497)", - "category": "security" - }, - { - "file": "test/openshell-0.0.99-migration-review.test.ts", - "test": "keeps every managed Docker policy identity explicit for workspace compatibility (#8662)", + "file": "test/node-tar-dockerfile-contract.test.ts", + "test": "rejects an isolated unreviewed Deep Agents Code Node base pin", "category": "security" }, - { - "file": "test/onboard-performance-config-schema.test.ts", - "test": "keeps baseline budgets derived from the checked-in samples", - "category": "compatibility" - }, - { - "file": "test/onboard-performance-config-schema.test.ts", - "test": "keeps interim cap adjustments tied to functional post-change evidence", - "category": "compatibility" - }, - { - "file": "test/onboard-performance-config-schema.test.ts", - "test": "keeps the authoritative local-build allowance tied to exact PR evidence", - "category": "compatibility" - }, - { - "file": "test/onboard-performance-config-schema.test.ts", - "test": "records five independent successful samples for current main", - "category": "compatibility" - }, { "file": "test/openclaw-2026-6-npm-remediation.test.ts", "test": "rebuilds a guarded core archive with the patched fs-safe package bundled", @@ -366,31 +106,11 @@ "test": "replaces the reviewed OpenClaw core tar and brace-expansion graph", "category": "security" }, - { - "file": "test/node-tar-dockerfile-contract.test.ts", - "test": "rejects an isolated unreviewed Deep Agents Code Node base pin", - "category": "security" - }, - { - "file": "test/openclaw-dependency-review.test.ts", - "test": "copies the legacy OpenClaw remediation helper before the base build invokes it", - "category": "security" - }, - { - "file": "test/openclaw-lifecycle-policy.test.ts", - "test": "cross-checks the allowlist against every production archive install boundary", - "category": "security" - }, { "file": "test/openclaw-locked-install.test.ts", "test": "fails closed on missing required packages and symlinked package roots", "category": "security" }, - { - "file": "test/openclaw-locked-install.test.ts", - "test": "invokes the locked installer before exposing OpenClaw in %s", - "category": "compatibility" - }, { "file": "test/openclaw-locked-install.test.ts", "test": "rejects $name even with a test-only matching lock digest", @@ -411,106 +131,6 @@ "test": "rejects symlinked package manifests", "category": "security" }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "publishes candidate contracts outside the all-agent activation pattern", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "does not grant package write permission to pull request candidate builds", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "imports the local base into Buildx for digest-only candidate publication", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "qualifies local and published candidates through the declared entrypoint", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "builds and validates the candidate image for linux/amd64 and linux/arm64", - "category": "compatibility" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "publishes a Pi base image for linux/amd64 and linux/arm64", - "category": "compatibility" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "grants network capability only to the approved image-owned binaries", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "merges a baked corporate CA into the trust bundle Node reads", - "category": "security" - }, - { - "file": "test/pi-candidate-runtime-artifacts.test.ts", - "test": "persists every merged CA variable into the runtime environment file", - "category": "security" - }, - { - "file": "test/platform-vitest-main-workflow.test.ts", - "test": "pins and verifies the Node.js archive in the trusted WSL helper", - "category": "security" - }, - { - "file": "test/platform-vitest-main-workflow.test.ts", - "test": "loads the WSL helper from trusted revisions before candidate execution (#6958)", - "category": "security" - }, - { - "file": "test/platform-vitest-main-workflow.test.ts", - "test": "keeps the WSL suite unprivileged with explicit root-only contracts", - "category": "security" - }, - { - "file": "test/platform-vitest-main-workflow.test.ts", - "test": "provisions the pinned macOS test runtime before running the full suite", - "category": "compatibility" - }, - { - "file": "test/plugin-vitest-project.test.ts", - "test": "defines one canonical plugin project for root and standalone runs", - "category": "compatibility" - }, - { - "file": "test/plugin-vitest-project.test.ts", - "test": "pilots assertion presence only in expect-based plugin tests (#6692)", - "category": "compatibility" - }, - { - "file": "test/pr-review-advisor-openshell-workflow-boundary.test.ts", - "test": "binds host-prepared GitHub context to the selected repository and pull request", - "category": "compatibility" - }, - { - "file": "test/pr-review-advisor-openshell-workflow-boundary.test.ts", - "test": "fails closed around the credential-free OpenShell filesystem and network boundary", - "category": "security" - }, - { - "file": "test/pr-review-advisor-openshell-workflow-boundary.test.ts", - "test": "keeps GitHub and upstream model credentials in separate host-only steps", - "category": "security" - }, - { - "file": "test/pr-review-advisor-openshell-workflow-boundary.test.ts", - "test": "pins trusted helper and bind sources to their checkout directories", - "category": "security" - }, - { - "file": "test/pr-review-advisor-openshell-workflow-boundary.test.ts", - "test": "preserves credential-free unavailable artifacts for manual dry runs", - "category": "compatibility" - }, { "file": "test/pr-review-advisor-workflow-boundary.test.ts", "test": "rejects deleting or weakening analysis-workspace symlink removal", @@ -526,46 +146,6 @@ "test": "executes pull request installer hash checks only from the PR base SHA", "category": "security" }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "keeps migrated provider identities and implementations behind the one bundle composition", - "category": "compatibility" - }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "activates Docker llama.cpp only through its durable lifecycle controller (#8433)", - "category": "security" - }, - { - "file": "test/source-architecture.test.ts", - "test": "keeps removed step mutation APIs out of production source (#7703)", - "category": "compatibility" - }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "keeps the dormant managed-bootstrap protocol driver-neutral", - "category": "security" - }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "keeps central activation paths disconnected from driver bootstrap adapters", - "category": "security" - }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "composes Docker bootstrap locally while keeping Kubernetes unsupported", - "category": "security" - }, - { - "file": "test/runtime-provider-source-shape.test.ts", - "test": "packages the dormant managed-bootstrap native boundary for every agent image", - "category": "security" - }, - { - "file": "test/release-latest-tag-workflow.test.ts", - "test": "binds latest promotion to the exact GitHub-verified tag object", - "category": "security" - }, { "file": "test/repro-4538-raw-doctor-perms.test.ts", "test": "emitted openclaw() guard restores the contract AND preserves a nonzero exit", @@ -585,76 +165,6 @@ "file": "test/repro-5978-policy-denial-hint.test.ts", "test": "prints only once when the file is sourced twice in one login shell", "category": "compatibility" - }, - { - "file": "test/runner.test.ts", - "test": "walkthrough.sh does not embed NVIDIA_INFERENCE_API_KEY in tmux or sandbox commands", - "category": "security" - }, - { - "file": "test/starter-prompt-docs.test.ts", - "test": "prepares the Starter Prompt in every docs build entry point (#5048)", - "category": "compatibility" - }, - { - "file": "test/validate-blueprint.test.ts", - "test": "pins the sandbox image by digest instead of a mutable tag (#1438)", - "category": "security" - }, - { - "file": "test/validate-blueprint.test.ts", - "test": "populates the top-level digest field with the image digest (#1438)", - "category": "security" - }, - { - "file": "test/vitest-coverage-thresholds.test.ts", - "test": "enforces the exact per-file security floors for full and merged coverage (#6692)", - "category": "security" - }, - { - "file": "test/vitest-developer-feedback.test.ts", - "test": "lets Vitest select reporters and preserves failed-test logs in CI (#6692)", - "category": "compatibility" - }, - { - "file": "test/vitest-state-isolation.test.ts", - "test": "keeps root and live projects free of unvalidated automatic cleanup", - "category": "security" - }, - { - "file": "test/vitest-state-isolation.test.ts", - "test": "keeps standalone plugin runs aligned without enabling mockReset", - "category": "compatibility" - }, - { - "file": "test/vitest-temp-root.test.ts", - "test": "wires cleanup into root and standalone plugin test runs", - "category": "compatibility" - }, - { - "file": "test/vitest-temp-root.test.ts", - "test": "isolates stateful non-live projects without redirecting live E2E state", - "category": "security" - }, - { - "file": "test/vitest-watch-triggers.test.ts", - "test": "registers the focused mappings at the root configuration boundary (#6692)", - "category": "compatibility" - }, - { - "file": "test/growth-guardrails-workflow-boundary.test.ts", - "test": "flags %s", - "category": "security" - }, - { - "file": "src/lib/state/sandbox-backup-sanitization.test.ts", - "test": "returns a credential-free JSON manifest byte for byte", - "category": "security" - }, - { - "file": "src/lib/state/sandbox-backup-sanitization.test.ts", - "test": "leaves an installed package manifest that names a credential-shaped dependency", - "category": "security" } ] } diff --git a/internal/security-reviews/openclaw-2026.6.10-dependency-review.md b/internal/security-reviews/openclaw-2026.6.10-dependency-review.md index 9235e7014a6..3d06d37fdd7 100644 --- a/internal/security-reviews/openclaw-2026.6.10-dependency-review.md +++ b/internal/security-reviews/openclaw-2026.6.10-dependency-review.md @@ -221,7 +221,7 @@ Isolated `node:22-trixie-slim` containers globally installed the reviewed OpenCl Invalid state: any reviewed archive install can run package-controlled install hooks, a package other than an exact allowlisted OpenClaw version receives an explicit lifecycle invocation, or the allowed manifest command/path changes without review. Source boundary: the five Docker install transactions, `installOpenClawMessagingPlugins`, and `ci/reviewed-npm-lifecycle-allowlist.json`. Source-fix constraint: lifecycle suppression must remain caller-controlled even while OpenClaw's plugin installer independently applies the same policy; do not replace the fixed postinstall command with `npm rebuild`, `npm run` against an unverified package spec, or a blanket script enablement. -Regression tests: `test/openclaw-lifecycle-policy.test.ts` pins the complete reviewed package set and the two exact exceptions; the integrity-pin base and plugin-install suites, `test/fetch-guard-patch-regression.test.ts`, and `test/messaging-build-applier.test.ts` pin script suppression and the fixed postinstall command at the execution boundaries. +Regression tests: the integrity-pin base and plugin-install suites, `test/fetch-guard-patch-regression.test.ts`, and `test/messaging-build-applier.test.ts` exercise script suppression and the fixed postinstall command at the execution boundaries. Removal condition: re-audit manifests, shrinkwrap `hasInstallScript` entries, and native prebuild coverage on every OpenClaw/plugin bump; remove an exception when the reviewed package no longer needs it, and never carry an exception to a new version implicitly. #### Messaging Plugin Registry Provenance Boundary diff --git a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts index f154c6c9a16..49c6503e88b 100644 --- a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts +++ b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts @@ -119,54 +119,6 @@ describe("MCP CLI input validation", () => { } }); - // source-shape-contract: compatibility -- Pinned OpenShell child-visible keys must drive credential rejection through every MCP boundary - it("rejects OpenShell child-environment compatibility keys as MCP credentials", () => { - for (const name of childVisibleCredentialManifest.rawChildValueKeys) { - expect(() => - parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", "--env", name]), - ).toThrow(/materialized as a raw child-process value/); - expect(() => resolveCredentialEnv([{ name, value: "host-only-secret" }])).toThrow( - /preserve the host-only credential boundary/, - ); - expect(() => - buildMcpBridgeProviderArgs("create", "provider", [{ name }], { - [name]: "host-only-secret", - }), - ).toThrow(/materialized as a raw child-process value/); - } - - for (const name of childVisibleCredentialManifest.rewrittenChildValueKeys) { - expect(() => - parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", "--env", name]), - ).toThrow(/rewritten by OpenShell's Google Cloud metadata compatibility path/); - } - }); - - // source-shape-contract: compatibility -- Host subprocess controls must stay synchronized with the pinned OpenShell child environment boundary - it("rejects host subprocess control and allowlist names as MCP credentials", () => { - for (const name of SUBPROCESS_ENV_ALLOWED_NAMES) { - expect(childVisibleCredentialManifest.runtimeControlKeys).toContain(name); - } - for (const prefix of SUBPROCESS_ENV_ALLOWED_PREFIXES) { - expect(childVisibleCredentialManifest.runtimeControlPrefixes).toContain(prefix); - } - for (const name of [ - "PATH", - "HOME", - "HTTP_PROXY", - "SSL_CERT_FILE", - "KUBECONFIG", - "LC_ALL", - "XDG_CONFIG_HOME", - "OPENSHELL_GATEWAY", - "GRPC_TRACE", - ]) { - expect(() => - parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", "--env", name]), - ).toThrow(/reserved for host subprocess control/); - } - }); - it("rejects sandbox runtime-control names as MCP credentials", () => { for (const name of [ "BASH_ENV", diff --git a/src/lib/agent/base-image-hermes.test.ts b/src/lib/agent/base-image-hermes.test.ts index 0f72bda7a33..ca796567419 100644 --- a/src/lib/agent/base-image-hermes.test.ts +++ b/src/lib/agent/base-image-hermes.test.ts @@ -40,118 +40,6 @@ describe("agent base image provisioning", () => { }); }); - // source-shape-contract: security -- Ordinary onboarding must use the pinned Hermes base image and check installed dependency versions after messaging package installation. - it("requires the pinned Hermes base image and checks installed dependency versions after messaging package installation (#8328)", () => { - const dockerfilePath = path.resolve(import.meta.dirname, "../../../agents/hermes/Dockerfile"); - const dockerfile = fs.readFileSync(dockerfilePath, "utf8"); - const trackedRef = dockerfile.match( - /^ARG BASE_IMAGE=(ghcr\.io\/nvidia\/nemoclaw\/hermes-sandbox-base@(sha256:[0-9a-f]{64}))$/m, - ); - expect(trackedRef).not.toBeNull(); - expect(trackedRef?.[1]).toBe( - "ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@sha256:ffafa4dd1d8d5a802ae4fc4005b51e1accfa5e782e47de736a0d8d8bf2c83837", - ); - - const messagingInstallIndex = dockerfile.indexOf("RUN unset SSL_CERT_FILE REQUESTS_CA_BUNDLE"); - const managedInstallIndex = dockerfile.indexOf( - "RUN --network=none --mount=from=hermes-managed-teams-wheels", - ); - const installLayer = dockerRunCommandBetween( - dockerfile, - "RUN --network=none --mount=from=hermes-managed-teams-wheels", - "WORKDIR /sandbox", - ).replace(/\s+/gu, " "); - const versionGuard = - "/opt/hermes/.venv/bin/python -I -c \"from importlib.metadata import version; expected = {'aiohttp': '3.14.3', 'cryptography': '50.0.0'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual\""; - const versionGuardIndex = installLayer.indexOf(versionGuard); - const finalConditionalEnd = [...installLayer.matchAll(/\bfi\b/gu)].at(-1)?.index ?? -1; - - expect(messagingInstallIndex).toBeGreaterThanOrEqual(0); - expect(managedInstallIndex).toBeGreaterThan(messagingInstallIndex); - expect(versionGuardIndex).toBeGreaterThan(finalConditionalEnd); - expect(installLayer).not.toContain("'aiohttp': '3.14.1'"); - expect(installLayer).not.toContain("'cryptography': '48.0.1'"); - - withMockedDocker(({ ensureAgentBaseImage, resolveSandboxBaseImageMock }) => { - resolveSandboxBaseImageMock.mockReturnValue({ - ref: trackedRef?.[1], - digest: trackedRef?.[2], - source: "source-sha", - glibcVersion: "2.41", - }); - - expect(ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toEqual({ - imageTag: trackedRef?.[1], - built: false, - }); - expect(resolveSandboxBaseImageMock).toHaveBeenCalledWith( - expect.objectContaining({ - pinnedRemoteRef: trackedRef?.[1], - preferPinnedRemoteRef: true, - }), - ); - - const platformDigest = - "sha256:c0c149ed03b3e8fcd3e395558b22e871cd27c9966ea6faf04c0d2b94d0a821b9"; - const platformDigestRef = `ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@${platformDigest}`; - resolveSandboxBaseImageMock.mockReturnValue({ - ref: platformDigestRef, - digest: platformDigest, - source: "pinned", - pinnedRemoteRef: trackedRef?.[1], - glibcVersion: "2.41", - }); - expect(ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toEqual({ - imageTag: platformDigestRef, - built: false, - }); - - const wrongNamespaceRef = `ghcr.io/nvidia/nemoclaw/other-hermes-base@${platformDigest}`; - resolveSandboxBaseImageMock.mockReturnValue({ - ref: wrongNamespaceRef, - digest: platformDigest, - source: "pinned", - pinnedRemoteRef: trackedRef?.[1], - glibcVersion: "2.41", - }); - expect(() => ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toThrow( - "Hermes final image does not accept base image ref", - ); - - resolveSandboxBaseImageMock.mockReturnValue({ - ref: platformDigestRef, - digest: platformDigest, - source: "latest", - glibcVersion: "2.41", - }); - expect(() => ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toThrow( - "Hermes final image does not accept base image ref", - ); - - resolveSandboxBaseImageMock.mockReturnValue({ - ref: platformDigestRef, - digest: platformDigest, - source: "pinned", - pinnedRemoteRef: `ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@sha256:${"2".repeat(64)}`, - glibcVersion: "2.41", - }); - expect(() => ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toThrow( - "Hermes final image does not accept base image ref", - ); - - const differentRef = `ghcr.io/nvidia/nemoclaw/hermes-sandbox-base@sha256:${"0".repeat(64)}`; - resolveSandboxBaseImageMock.mockReturnValue({ - ref: differentRef, - digest: `sha256:${"0".repeat(64)}`, - source: "source-sha", - glibcVersion: "2.41", - }); - expect(() => ensureAgentBaseImage(makeAgent({ dockerfilePath }))).toThrow( - "Hermes final image does not accept base image ref", - ); - }); - }); - it("fails before candidate resolution when the Hermes final Dockerfile is unreadable", () => { withMockedDocker(({ ensureAgentBaseImage, resolveSandboxBaseImageMock }) => { expect(() => diff --git a/src/lib/agent/state-directory-contract.test.ts b/src/lib/agent/state-directory-contract.test.ts index 9478bdca0a8..099f96cbd22 100644 --- a/src/lib/agent/state-directory-contract.test.ts +++ b/src/lib/agent/state-directory-contract.test.ts @@ -144,25 +144,6 @@ describe("agent state directory contract", () => { ).toEqual(testCase.expectedMutablePaths); }); - // source-shape-contract: security -- Generated image plans must match the reviewed AgentDefinition projection - it("keeps generated image plans equal to their AgentDefinition projections (#8006)", () => { - const imagePlanAgents = listAgents().filter( - (agentName) => loadAgent(agentName).stateLockPlanInImage, - ); - for (const agentName of imagePlanAgents) { - const generated = JSON.parse( - fs.readFileSync( - path.join(process.cwd(), "agents", agentName, "state-lock-plan.json"), - "utf8", - ), - ) as Record; - const { $comment, ...plan } = generated; - - expect(typeof $comment).toBe("string"); - expect(plan).toEqual(loadAgent(agentName).stateLockPlan); - } - }); - it.each([ [{ state_dirs: "state" }, /state_dirs.*array/], [{ state_dirs: ["../state"] }, /canonical relative path/], diff --git a/src/lib/onboard/inference-providers/compatible-endpoint-gateway-route.test.ts b/src/lib/onboard/inference-providers/compatible-endpoint-gateway-route.test.ts index 4ab01174fde..39f78088c91 100644 --- a/src/lib/onboard/inference-providers/compatible-endpoint-gateway-route.test.ts +++ b/src/lib/onboard/inference-providers/compatible-endpoint-gateway-route.test.ts @@ -13,25 +13,6 @@ import { } from "./compatible-endpoint-gateway-route"; describe("compatible endpoint gateway routing", () => { - // source-shape-contract: compatibility -- Bundled loopback routing must match the shipped host-gateway policy ports - it("matches the bundled local-inference host-gateway ports (#5744)", () => { - const policyPath = path.resolve( - import.meta.dirname, - "../../../../nemoclaw-blueprint/policies/presets/local-inference.yaml", - ); - const policy = YAML.parse(fs.readFileSync(policyPath, "utf8")); - const endpoints: Array<{ host?: string; port?: number }> = - policy.network_policies.local_inference.endpoints; - const hostGatewayPorts = endpoints - .filter(({ host }) => host === "host.openshell.internal") - .map(({ port }) => port) - .sort((left, right) => (left ?? 0) - (right ?? 0)); - - expect(hostGatewayPorts).toEqual( - [...BUNDLED_LOCAL_INFERENCE_GATEWAY_PORTS].sort((left, right) => left - right), - ); - }); - it("rewrites exact HTTP loopback hosts on bundled local-inference ports (#5744)", () => { for (const host of ["localhost", "127.0.0.1", "[::1]"]) { for (const port of COMPATIBLE_ENDPOINT_GATEWAY_PORTS) { diff --git a/src/lib/onboard/managed-startup-profile.test.ts b/src/lib/onboard/managed-startup-profile.test.ts index 5ef0c881c2a..60d2956a6e6 100644 --- a/src/lib/onboard/managed-startup-profile.test.ts +++ b/src/lib/onboard/managed-startup-profile.test.ts @@ -467,57 +467,6 @@ describe("managed startup profile", () => { ).toThrow(/not supported/); }); - // source-shape-contract: compatibility -- Every shipped Docker build input must map to versioned startup intent or a declared build-only exclusion - it("classifies every stock Docker ARG as startup-affordance or deliberate exclusion", () => { - for (const agent of MANAGED_STARTUP_AGENTS) { - const classified = new Set([ - ...MANAGED_STARTUP_PROFILE_AFFORDANCE_INVENTORY[agent].map(({ input }) => input), - ...MANAGED_STARTUP_PROFILE_EXCLUDED_DOCKER_INPUTS[agent].map(({ input }) => input), - ]); - expect([...STOCK_DOCKER_ARGS[agent]].filter((input) => !classified.has(input))).toEqual([]); - } - }); - - // source-shape-contract: compatibility -- Every centralized agent runtime input must map to versioned startup intent or a typed downstream owner - it("classifies every centralized runtime input as profile intent or an explicit deferral", () => { - expect([...STOCK_RUNTIME_INPUTS].sort()).toEqual( - Object.keys(STOCK_RUNTIME_INPUT_AGENTS).sort(), - ); - const missing = Object.entries(STOCK_RUNTIME_INPUT_AGENTS).flatMap(([input, agents]) => - agents - .filter( - (agent) => - !new Set([ - ...MANAGED_STARTUP_PROFILE_AFFORDANCE_INVENTORY[agent].map( - ({ input: profileInput }) => profileInput, - ), - ...MANAGED_STARTUP_PROFILE_DEFERRED_RUNTIME_INPUTS[agent].map( - ({ input: deferredInput }) => deferredInput, - ), - ]).has(input), - ) - .map((agent) => `${agent}:${input}`), - ); - expect(missing).toEqual([]); - - const openClawAutoPairInputs = MANAGED_STARTUP_PROFILE_DEFERRED_RUNTIME_INPUTS.openclaw.filter( - ({ input }) => input.startsWith("NEMOCLAW_AUTO_PAIR_"), - ); - expect([...OPENCLAW_AUTO_PAIR_CONSUMER_INPUTS].sort()).toEqual( - openClawAutoPairInputs.map(({ input }) => input).sort(), - ); - expect( - Object.fromEntries(openClawAutoPairInputs.map(({ admission, input }) => [input, admission])), - ).toEqual({ - NEMOCLAW_AUTO_PAIR_DEADLINE_SECS: "managed-launch-forwarded", - NEMOCLAW_AUTO_PAIR_FAST_DEADLINE_SECS: "managed-launch-forwarded", - NEMOCLAW_AUTO_PAIR_FAST_REENTRY_INTERVAL_SECS: "managed-launch-forwarded", - NEMOCLAW_AUTO_PAIR_FAST_REENTRY_POLLS: "managed-launch-forwarded", - NEMOCLAW_AUTO_PAIR_RUN_TIMEOUT_SECS: "managed-launch-forwarded", - NEMOCLAW_AUTO_PAIR_SLOW_INTERVAL_SECS: "managed-launch-forwarded", - }); - }); - it("records generic cross-agent emissions as cleanup obligations, not supported semantics", () => { expect(MANAGED_STARTUP_RUNTIME_CLEANUP_OBLIGATIONS).toHaveLength(2); for (const obligation of MANAGED_STARTUP_RUNTIME_CLEANUP_OBLIGATIONS) { diff --git a/test/agent-variant-docs.test.ts b/test/agent-variant-docs.test.ts index 039ef9a587e..4d2863cad19 100644 --- a/test/agent-variant-docs.test.ts +++ b/test/agent-variant-docs.test.ts @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import { readFileSync } from "node:fs"; - import { describe, expect, it } from "vitest"; import { renderAgentVariantPage } from "../scripts/sync-agent-variant-docs.mts"; @@ -32,97 +30,6 @@ Use \`$$nemoclaw\` for the current variant. `; describe("agent variant docs", () => { - // source-shape-contract: compatibility -- OpenClaw workspace documentation must list every runtime-seeded template so generated variants cannot omit operator-visible files. - it("keeps the OpenClaw workspace inventory aligned with seeded runtime templates", () => { - const workspaceFiles = readFileSync( - new URL("../docs/manage-sandboxes/workspace-files.mdx", import.meta.url), - "utf8", - ); - const startScript = readFileSync( - new URL("../scripts/nemoclaw-start.sh", import.meta.url), - "utf8", - ); - const seedFunction = startScript.slice( - startScript.indexOf("seed_default_workspace_templates()"), - ); - const seededFiles = seedFunction - .match(/for file in ([^;]+); do/)?.[1] - .trim() - .split(/\s+/); - - expect(seededFiles).toEqual([ - "AGENTS.md", - "SOUL.md", - "IDENTITY.md", - "USER.md", - "TOOLS.md", - "HEARTBEAT.md", - ]); - const expectedSeededFiles = seededFiles ?? []; - const deferredFiles = ["MEMORY.md", "memory/"]; - - const rendered = renderAgentVariantPage(workspaceFiles, "openclaw", { - sourcePath: "/repo/docs/manage-sandboxes/workspace-files.mdx", - }); - expect(rendered).toContain( - "when the default workspace directory exists, is not a symbolic link, and is empty", - ); - expect(rendered).toContain( - "Set `NEMOCLAW_MINIMAL_BOOTSTRAP=1` before onboarding to skip default workspace template seeding.", - ); - const fileReference = rendered.match( - /## File Reference\n\n([\s\S]*?)\n\n## Where They Live/, - )?.[1]; - const tableFiles = Array.from( - fileReference?.matchAll(/^\| `([^`]+)` \|/gm) ?? [], - (match) => match[1], - ); - expect(tableFiles.filter((file) => !deferredFiles.includes(file)).sort()).toEqual( - [...expectedSeededFiles].sort(), - ); - expect(tableFiles.filter((file) => deferredFiles.includes(file)).sort()).toEqual( - [...deferredFiles].sort(), - ); - - const workspaceTree = rendered.match( - /```text\n\/sandbox\/\.openclaw\/workspace\/\n([\s\S]*?)\n```/, - )?.[1]; - const treeFiles = Array.from( - workspaceTree?.matchAll(/^[├└]── ([^\s]+)/gm) ?? [], - (match) => match[1], - ); - for (const file of expectedSeededFiles) { - expect(tableFiles).toContain(file); - expect(treeFiles).toContain(file); - } - expect(treeFiles.filter((file) => !deferredFiles.includes(file)).sort()).toEqual( - [...expectedSeededFiles].sort(), - ); - expect(treeFiles.filter((file) => deferredFiles.includes(file)).sort()).toEqual( - [...deferredFiles].sort(), - ); - - const multiAgentSection = rendered.match( - /## Multi-Agent Deployments\n\n([\s\S]*?)\n\n## Persistence Behavior/, - )?.[1]; - const seededSummary = multiAgentSection?.match( - /same seeded Markdown file structure[^:]*: ([^\n]+)\n/, - )?.[1]; - const deferredSummary = multiAgentSection?.match( - /OpenClaw creates ([^\n]+) separately in each workspace/, - )?.[1]; - const summarySeededFiles = Array.from( - seededSummary?.matchAll(/`([^`]+)`/g) ?? [], - (match) => match[1], - ); - const summaryDeferredFiles = Array.from( - deferredSummary?.matchAll(/`([^`]+)`/g) ?? [], - (match) => match[1], - ); - expect(summarySeededFiles.sort()).toEqual([...expectedSeededFiles].sort()); - expect(summaryDeferredFiles.sort()).toEqual([...deferredFiles].sort()); - }); - it("renders OpenClaw placeholder code and content", () => { const rendered = renderAgentVariantPage(source, "openclaw"); @@ -280,182 +187,5 @@ import { AgentOnly } from "../_components/AgentGuide"; expect(rendered).toContain("![Diagram](../../../manage-sandboxes/images/diagram.png)"); }); - it("renders strict Landlock troubleshooting for Deep Agents only", () => { - const troubleshooting = readFileSync( - new URL("../docs/reference/troubleshooting.mdx", import.meta.url), - "utf8", - ); - const deepAgents = renderAgentVariantPage(troubleshooting, "deepagents", { - sourcePath: "/repo/docs/reference/troubleshooting.mdx", - }); - const openclaw = renderAgentVariantPage(troubleshooting, "openclaw", { - sourcePath: "/repo/docs/reference/troubleshooting.mdx", - }); - - expect(deepAgents).toContain("### Landlock filesystem policy blocks sandbox startup"); - expect(deepAgents).toContain("Deep Agents uses strict Landlock compatibility."); - expect(deepAgents).toContain( - "OpenShell refuses to start the sandbox instead of silently degrading.", - ); - expect(deepAgents).not.toContain("### Landlock filesystem restrictions silently degraded"); - expect(deepAgents).not.toContain("best_effort mode"); - expect(deepAgents).not.toContain( - "This warning is informational and does not block sandbox creation.", - ); - - expect(openclaw).toContain("### Landlock filesystem restrictions silently degraded"); - expect(openclaw).toContain("best_effort mode"); - expect(openclaw).not.toContain("### Landlock filesystem policy blocks sandbox startup"); - }); - - it("does not render managed web-search troubleshooting for Deep Agents", () => { - const troubleshooting = readFileSync( - new URL("../docs/reference/troubleshooting.mdx", import.meta.url), - "utf8", - ); - const deepAgents = renderAgentVariantPage(troubleshooting, "deepagents", { - sourcePath: "/repo/docs/reference/troubleshooting.mdx", - }); - const openclaw = renderAgentVariantPage(troubleshooting, "openclaw", { - sourcePath: "/repo/docs/reference/troubleshooting.mdx", - }); - - expect(deepAgents).toContain("### Tavily remains blocked after opt-in"); - expect(deepAgents).toContain( - "Deep Agents does not have a NemoClaw-managed web-search feature.", - ); - expect(deepAgents).not.toContain("### Web search verification reports a warning"); - expect(deepAgents).not.toContain( - "When web search is enabled, onboarding checks the selected agent configuration", - ); - expect(deepAgents).not.toContain( - "Rerunning onboarding with a different provider recreates the sandbox", - ); - - expect(openclaw).toContain("### Web search verification reports a warning"); - expect(openclaw).not.toContain( - "Deep Agents does not have a NemoClaw-managed web-search feature.", - ); - }); - - it("lists only implemented commands in manifest iteration guidance (#7308)", () => { - const manifest = readFileSync( - new URL("../docs/inference/declarative-agents-manifest.mdx", import.meta.url), - "utf8", - ); - const rendered = renderAgentVariantPage(manifest, "openclaw", { - sourcePath: "/repo/docs/inference/declarative-agents-manifest.mdx", - }); - const iteratingStart = rendered.indexOf("## Iterating"); - const iteratingEnd = rendered.indexOf("## Apply to an Existing Sandbox", iteratingStart); - const iterating = rendered.slice(iteratingStart, iteratingEnd); - - expect(iteratingStart).toBeGreaterThanOrEqual(0); - expect(iteratingEnd).toBeGreaterThan(iteratingStart); - expect(iterating).toContain("agents add|delete|list"); - expect(iterating).toContain("agents apply -f "); - expect(iterating).not.toContain("agents show"); - }); - - it("renders provider-switch instructions for the applicable agent variants (#7309)", () => { - const source = readFileSync( - new URL("../docs/inference/switch-providers.mdx", import.meta.url), - "utf8", - ); - const render = (variant: "openclaw" | "hermes" | "deepagents") => - renderAgentVariantPage(source, variant, { - sourcePath: "/repo/docs/inference/switch-providers.mdx", - }); - const openclaw = render("openclaw"); - const hermes = render("hermes"); - const deepAgents = render("deepagents"); - const recreationHeading = "## Recreate a Deep Agents Sandbox"; - const namedSandboxSyntax = - "The `shields` commands take a positional name. `inference set` takes `--sandbox `."; - - expect(openclaw).toContain(namedSandboxSyntax); - expect(openclaw).toContain("nemoclaw shields down"); - expect(openclaw).not.toContain(recreationHeading); - expect(hermes).toContain(namedSandboxSyntax); - expect(hermes).toContain("nemohermes shields down"); - expect(hermes).not.toContain(recreationHeading); - expect(deepAgents).toContain(recreationHeading); - expect(deepAgents).not.toContain(namedSandboxSyntax); - }); - - it("excludes OpenClaw gateway behavior from Hermes provider switching (#7902)", () => { - const source = readFileSync( - new URL("../docs/inference/switch-providers.mdx", import.meta.url), - "utf8", - ); - const render = (variant: "openclaw" | "hermes") => - renderAgentVariantPage(source, variant, { - sourcePath: "/repo/docs/inference/switch-providers.mdx", - }); - const openclaw = render("openclaw"); - const hermes = render("hermes"); - const openClawGatewayBehavior = "restarts only the OpenClaw gateway and verifies its health"; - - expect(openclaw).toContain(openClawGatewayBehavior); - expect(hermes).not.toContain( - "updates the provider namespace and selected model in the running configuration", - ); - expect(hermes).not.toContain( - "Changes within the current API family hot-reload without replacing the gateway process", - ); - expect(hermes).not.toContain(openClawGatewayBehavior); - expect(hermes).toContain("a normal runtime route change does not rebuild or restart Hermes"); - }); - - it("renders the Hermes baseline-policy explanation once (#7903)", () => { - const source = readFileSync( - new URL("../docs/reference/network-policies.mdx", import.meta.url), - "utf8", - ); - const hermes = renderAgentVariantPage(source, "hermes", { - sourcePath: "/repo/docs/reference/network-policies.mdx", - }); - const baselineExplanation = - "Hermes sandboxes use an agent-specific baseline policy in `agents/hermes/policy-additions.yaml`"; - - expect(hermes.split(baselineExplanation)).toHaveLength(2); - }); - - it("renders the shared Hermes WhatsApp session path without a configuration repair (#8184)", () => { - const whatsapp = readFileSync( - new URL("../docs/manage-sandboxes/set-up-whatsapp.mdx", import.meta.url), - "utf8", - ); - const hermes = renderAgentVariantPage(whatsapp, "hermes", { - sourcePath: "/repo/docs/manage-sandboxes/set-up-whatsapp.mdx", - }); - - expect(hermes).toContain( - "Hermes dashboard pairing and the gateway share `/sandbox/.hermes/platforms/whatsapp/session`", - ); - expect(hermes).toContain("nemohermes channels status --channel whatsapp"); - expect(hermes).toContain("nemohermes channels remove whatsapp"); - expect(hermes).not.toContain("platforms.whatsapp.extra.session_path"); - }); - it("keeps the troubleshooting security guidance link within each agent guide (#6558)", () => { - const troubleshooting = readFileSync( - new URL("../docs/reference/troubleshooting.mdx", import.meta.url), - "utf8", - ); - - for (const variant of ["openclaw", "hermes", "deepagents"] as const) { - const rendered = renderAgentVariantPage(troubleshooting, variant, { - outputPath: `/repo/docs/_build/agent-variants/reference/troubleshooting.${variant}.generated.mdx`, - sourcePath: "/repo/docs/reference/troubleshooting.mdx", - }); - - expect(rendered).toContain( - "[Gateway Compatibility Container](../security/security-controls/gateway-authentication-controls#gateway-compatibility-container)", - ); - expect(rendered).not.toMatch( - /\/user-guide\/(?:openclaw|hermes|deepagents)\/security\/security-controls\/gateway-authentication-controls/, - ); - } - }); }); diff --git a/test/code-change-considerations.test.ts b/test/code-change-considerations.test.ts index 50142d2b8d0..a817c372d9a 100644 --- a/test/code-change-considerations.test.ts +++ b/test/code-change-considerations.test.ts @@ -46,42 +46,6 @@ afterEach(() => { }); describe("shared code change considerations", () => { - // source-shape-contract: compatibility -- Canonical guidance ownership must prevent lifecycle and Advisor prompt copies from drifting - it("keeps the stage-neutral questions in one concise owner", () => { - const resource = fs.readFileSync(RESOURCE_PATH, "utf8"); - const consumers = [ - ".agents/skills/_shared/implementation-discovery.md", - ".agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md", - ].map(read); - const formerCopies = [ - "tools/pr-review-advisor/analyze.mts", - ".agents/skills/_shared/implementation-discovery.md", - ".agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md", - ].map(read); - - expect(resource.split("\n").length).toBeLessThan(40); - expect(resource).toContain("accepted outcome and current consumer"); - expect(resource).toContain("extended directly"); - expect(resource).toContain("ordering or concurrency"); - expect(resource).toContain("defaults, retries, recovery, and cleanup"); - expect(resource).toContain("paths can bypass the change"); - expect(resource).toContain("shortest stable test"); - expect(resource).toContain("runtime or end-to-end evidence"); - expect(resource).toContain("overlap, conflict, or affect delivery order"); - expect(resource).not.toMatch(/\bsrc\/|\btest\/|npm run|\.github\/workflows/u); - for (const consumer of consumers) { - expect(consumer).toContain("code-change-considerations.md"); - } - for (const consumer of formerCopies) { - expect(consumer).not.toContain( - "What accepted outcome and current consumer require the change?", - ); - expect(consumer).not.toContain( - "Which alternate entry, error, cached, resumed, or compatibility paths", - ); - } - }); - it("loads the resource from the trusted module checkout and embeds it once", () => { const originalCwd = process.cwd(); const untrustedCheckout = fs.mkdtempSync(path.join(tmpdir(), "advisor-considerations-")); diff --git a/test/corporate-ca-build-tls-anchor.test.ts b/test/corporate-ca-build-tls-anchor.test.ts deleted file mode 100644 index 0c066d72f54..00000000000 --- a/test/corporate-ca-build-tls-anchor.test.ts +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { readFileSync } from "node:fs"; -import { join } from "node:path"; -import { describe, expect, it } from "vitest"; -import { dockerfileInstructions } from "./helpers/dockerfile-run-commands"; - -const DOCKERFILE = join(import.meta.dirname, "../Dockerfile"); -const CORPORATE_CA_PATH = "/usr/local/share/nemoclaw/corporate-ca.pem"; - -function expectRunUsesConditionalNodeAndCurlTrust(stage: string, commandMarker: string): void { - const matches = dockerfileInstructions(stage).filter( - (instruction) => instruction.keyword === "RUN" && instruction.body.includes(commandMarker), - ); - expect(matches, commandMarker).toHaveLength(1); - const instruction = matches[0]; - - const guardIndex = instruction.text.indexOf(`if [ -f ${CORPORATE_CA_PATH} ]; then`); - const curlIndex = instruction.text.indexOf(`export CURL_CA_BUNDLE=${CORPORATE_CA_PATH}`); - const nodeIndex = instruction.text.indexOf(`export NODE_EXTRA_CA_CERTS=${CORPORATE_CA_PATH}`); - const commandIndex = instruction.text.indexOf(commandMarker); - - expect(guardIndex, `${commandMarker}: conditional CA guard`).toBeGreaterThan(-1); - expect(curlIndex, `${commandMarker}: curl CA export`).toBeGreaterThan(guardIndex); - expect(nodeIndex, `${commandMarker}: Node CA export`).toBeGreaterThan(curlIndex); - expect(commandIndex, `${commandMarker}: command order`).toBeGreaterThan(nodeIndex); -} - -describe("corporate proxy CA build-time TLS anchor (#6839)", () => { - const dockerfile = readFileSync(DOCKERFILE, "utf-8"); - - // source-shape-contract: security -- The single corporate CA build arg is the sole onboard-patched supply-chain trust input - it("declares exactly one corporate CA build arg so onboard patching stays unambiguous", () => { - const matches = dockerfile.match(/^ARG NEMOCLAW_CORPORATE_CA_B64=/gm) ?? []; - expect(matches).toHaveLength(1); - }); - - // source-shape-contract: security -- Every final-stage registry step must establish conditional trust inside its own Docker RUN - it("uses conditional Node and curl trust in every final-stage registry step", () => { - const argIndex = dockerfile.indexOf("ARG NEMOCLAW_CORPORATE_CA_B64="); - const finalFromIndex = dockerfile.indexOf("FROM ${BASE_IMAGE}"); - const finalStage = dockerfile.slice(finalFromIndex); - const decodeIndex = finalStage.indexOf('RUN if [ -n "${NEMOCLAW_CORPORATE_CA_B64}" ]; then'); - const registryStepMarkers = [ - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", - "node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts", - "node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts", - "/usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh --omit=dev", - "OPENCLAW_LOCK_SHA256=none-legacy-fixture", - ]; - - expect(dockerfile).not.toContain("ENV NODE_EXTRA_CA_CERTS="); - for (const [name, index] of Object.entries({ argIndex, finalFromIndex, decodeIndex })) { - expect(index, name).toBeGreaterThan(-1); - } - for (const commandMarker of registryStepMarkers) { - expectRunUsesConditionalNodeAndCurlTrust(finalStage, commandMarker); - } - }); -}); - -describe("DCode corporate proxy CA cold-build trust (#8119)", () => { - const baseDockerfile = readFileSync( - join(import.meta.dirname, "../agents/langchain-deepagents-code/Dockerfile.base"), - "utf-8", - ); - const finalDockerfile = readFileSync( - join(import.meta.dirname, "../agents/langchain-deepagents-code/Dockerfile"), - "utf-8", - ); - - // source-shape-contract: security -- DCode cold base builds must establish corporate CA trust before HTTPS dependency fetches - it("accepts the corporate CA build arg in the DCode base image before HTTPS fetches", () => { - const argIndex = baseDockerfile.indexOf("ARG NEMOCLAW_CORPORATE_CA_B64="); - const nativeBuilderIndex = baseDockerfile.indexOf("AS native-security-builder", argIndex); - const nativeArgIndex = baseDockerfile.indexOf( - "ARG NEMOCLAW_CORPORATE_CA_B64", - nativeBuilderIndex, - ); - const nativeTrustIndex = baseDockerfile.indexOf("update-ca-certificates", nativeArgIndex); - const nativeFetchIndex = baseDockerfile.indexOf( - "build-native-security-packages.sh /out", - nativeTrustIndex, - ); - const perlFetchIndex = baseDockerfile.indexOf( - "RUN bash /scripts/security/build-perl-security-packages.sh", - nativeFetchIndex, - ); - const finalFromIndex = baseDockerfile.indexOf("FROM node:22-trixie-slim", perlFetchIndex); - const finalArgIndex = baseDockerfile.indexOf("ARG NEMOCLAW_CORPORATE_CA_B64", finalFromIndex); - const finalTrustIndex = baseDockerfile.indexOf("update-ca-certificates", finalArgIndex); - const firstSnapshotCurlIndex = baseDockerfile.indexOf( - "https://snapshot.debian.org/archive", - finalTrustIndex, - ); - - for (const [name, index] of Object.entries({ - argIndex, - nativeBuilderIndex, - nativeArgIndex, - nativeTrustIndex, - nativeFetchIndex, - perlFetchIndex, - finalFromIndex, - finalArgIndex, - finalTrustIndex, - firstSnapshotCurlIndex, - })) { - expect(index, name).toBeGreaterThan(-1); - } - expect(nativeArgIndex).toBeLessThan(nativeTrustIndex); - expect(nativeTrustIndex).toBeLessThan(nativeFetchIndex); - expect(nativeFetchIndex).toBeLessThan(perlFetchIndex); - expect(finalArgIndex).toBeLessThan(finalTrustIndex); - expect(finalTrustIndex).toBeLessThan(firstSnapshotCurlIndex); - }); - - // source-shape-contract: security -- DCode discovery assembly must not make registry requests that bypass the final image trust anchor - it("copies the reviewed DCode discovery runtime without registry access", () => { - const discoveryStageIndex = finalDockerfile.indexOf("AS mcp-tool-discovery-runtime"); - const reviewedBundleIndex = finalDockerfile.indexOf( - "reviewed-runtime-bundle/mcp-tool-discovery/mcp-tool-discovery.bundle", - discoveryStageIndex, - ); - const discoveryStageEnd = finalDockerfile.indexOf("\nFROM ", reviewedBundleIndex); - const finalStageIndex = finalDockerfile.indexOf("FROM ${BASE_IMAGE}", discoveryStageEnd); - const discoveryStage = finalDockerfile.slice(discoveryStageIndex, discoveryStageEnd); - - expect(discoveryStageIndex).toBeGreaterThan(-1); - expect(reviewedBundleIndex).toBeGreaterThan(discoveryStageIndex); - expect(discoveryStageEnd).toBeGreaterThan(reviewedBundleIndex); - expect(finalStageIndex).toBeGreaterThan(discoveryStageEnd); - expect(discoveryStage).not.toContain("NEMOCLAW_CORPORATE_CA_B64"); - expect(discoveryStage).not.toContain("install-reviewed-runtime.sh"); - expect(discoveryStage).not.toContain("RUN "); - }); - - // source-shape-contract: security -- DCode final images must decode the sandbox-specific corporate CA even when the base is reused - it("decodes the corporate CA again in the DCode final image", () => { - const finalFromIndex = finalDockerfile.indexOf("FROM ${BASE_IMAGE}"); - const finalArgIndex = finalDockerfile.indexOf("ARG NEMOCLAW_CORPORATE_CA_B64", finalFromIndex); - const finalDecodeIndex = finalDockerfile.indexOf( - 'RUN if [ -n "${NEMOCLAW_CORPORATE_CA_B64}" ]; then', - finalArgIndex, - ); - const trustDirectoryIndex = finalDockerfile.indexOf( - "install -d -o root -g root -m 0755 /usr/local/share/nemoclaw", - finalDecodeIndex, - ); - const runtimeProbeIndex = finalDockerfile.indexOf( - "mcp-tool-discovery-runtime", - finalDecodeIndex, - ); - const curlAnchorIndex = finalDockerfile.indexOf( - "export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem", - finalDecodeIndex, - ); - const ipAddressPatchIndex = finalDockerfile.indexOf( - "node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts", - curlAnchorIndex, - ); - - for (const [name, index] of Object.entries({ - finalFromIndex, - finalArgIndex, - finalDecodeIndex, - trustDirectoryIndex, - runtimeProbeIndex, - curlAnchorIndex, - ipAddressPatchIndex, - })) { - expect(index, name).toBeGreaterThan(-1); - } - expect(finalFromIndex).toBeLessThan(finalArgIndex); - expect(finalArgIndex).toBeLessThan(finalDecodeIndex); - expect(finalDecodeIndex).toBeLessThan(trustDirectoryIndex); - expect(trustDirectoryIndex).toBeLessThan(runtimeProbeIndex); - expect(trustDirectoryIndex).toBeLessThan(curlAnchorIndex); - expect(curlAnchorIndex).toBeLessThan(ipAddressPatchIndex); - }); -}); - -describe("Hermes corporate proxy CA final-stage trust", () => { - const dockerfile = readFileSync( - join(import.meta.dirname, "../agents/hermes/Dockerfile"), - "utf-8", - ); - - // source-shape-contract: security -- Hermes final-stage registry clients must trust the decoded corporate CA before making HTTPS requests - it("uses the corporate CA conditionally for all Hermes registry remediations", () => { - const finalFromIndex = dockerfile.indexOf("FROM ${BASE_IMAGE}"); - const finalStage = dockerfile.slice(finalFromIndex); - const argIndex = finalStage.indexOf("ARG NEMOCLAW_CORPORATE_CA_B64"); - const decodeIndex = finalStage.indexOf( - 'RUN if [ -n "${NEMOCLAW_CORPORATE_CA_B64}" ]; then', - argIndex, - ); - const payloadCopyIndex = finalStage.indexOf("COPY --from=hermes-npm-patch-payload / /"); - const remediationCommands = [ - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", - "node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts", - "node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts", - ]; - const dashboardBuildCommand = "hermes_web_dist=/opt/hermes/hermes_cli/web_dist"; - const agentInstallCommand = - "node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase agent-install"; - const packageInstallRun = dockerfileInstructions(finalStage).find( - (instruction) => - instruction.keyword === "RUN" && instruction.body.includes(agentInstallCommand), - ); - const expectedPackageInstallRun = [ - "RUN unset SSL_CERT_FILE REQUESTS_CA_BUNDLE; \\", - " if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \\", - " export SSL_CERT_FILE=/usr/local/share/nemoclaw/corporate-ca.pem; \\", - " export REQUESTS_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \\", - " fi; \\", - ` ${agentInstallCommand}`, - "", - ].join("\n"); - const managedUnionInstallRun = dockerfileInstructions(finalStage).find( - (instruction) => - instruction.keyword === "RUN" && - instruction.body.includes("--agent hermes --phase managed-image-capability-union"), - ); - const expectedManagedUnionInstallRun = [ - "RUN --network=none --mount=from=hermes-managed-teams-wheels,target=/opt/nemoclaw-hermes-teams-wheels,ro \\", - ' if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then \\', - " UV_OFFLINE=true UV_FIND_LINKS=/opt/nemoclaw-hermes-teams-wheels \\", - " node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts \\", - " --agent hermes --phase managed-image-capability-union; \\", - " fi; \\", - " /opt/hermes/.venv/bin/python -I -c \\", - " \"from importlib.metadata import version; expected = {'aiohttp': '3.14.3', 'cryptography': '50.0.0'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual\"", - "", - ].join("\n"); - for (const [name, index] of Object.entries({ - finalFromIndex, - argIndex, - decodeIndex, - payloadCopyIndex, - })) { - expect(index, name).toBeGreaterThan(-1); - } - expect(finalStage).not.toContain("ENV NODE_EXTRA_CA_CERTS="); - expect(argIndex).toBeLessThan(decodeIndex); - expect(decodeIndex).toBeLessThan(payloadCopyIndex); - for (const remediationCommand of remediationCommands) { - expectRunUsesConditionalNodeAndCurlTrust(finalStage, remediationCommand); - } - expectRunUsesConditionalNodeAndCurlTrust(finalStage, dashboardBuildCommand); - expect(packageInstallRun?.text).toBe(expectedPackageInstallRun); - expect(packageInstallRun?.text).not.toContain("else"); - expect(managedUnionInstallRun?.text).toBe(expectedManagedUnionInstallRun); - expect(finalStage.match(/^ENV (?:SSL_CERT_FILE|REQUESTS_CA_BUNDLE)=/gmu) ?? []).toEqual([]); - }); -}); diff --git a/test/e2e-fixture-dependency-review.test.ts b/test/e2e-fixture-dependency-review.test.ts index 8ab650980e4..25a10cb1f88 100644 --- a/test/e2e-fixture-dependency-review.test.ts +++ b/test/e2e-fixture-dependency-review.test.ts @@ -51,34 +51,4 @@ describe("E2E fixture dependency review", () => { } }); - // source-shape-contract: security -- Exact fixture pins and reviewed lock integrity constrain untrusted dependency code - it("keeps installed fixture dependencies on exact versions", () => { - const weatherFixture = path.join(FIXTURES_ROOT, "plugins", "weather"); - const manifest = JSON.parse( - fs.readFileSync(path.join(weatherFixture, "package.json"), "utf8"), - ) as { - dependencies?: Record; - devDependencies?: Record; - }; - for (const [name, version] of Object.entries({ - ...manifest.dependencies, - ...manifest.devDependencies, - })) { - expect(version, name).toMatch(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/); - } - - const lockfileText = fs.readFileSync(path.join(weatherFixture, "package-lock.json"), "utf8"); - const lockfileDigest = createHash("sha256").update(lockfileText).digest("hex"); - expect(review).toContain(`SHA-256 \`${lockfileDigest}\``); - - const lockfile = JSON.parse(lockfileText) as { - packages?: Record; - }; - for (const [packagePath, entry] of Object.entries(lockfile.packages ?? {}).filter( - ([packagePath]) => packagePath.length > 0, - )) { - expect(entry.resolved, packagePath).toEqual(expect.any(String)); - expect(entry.integrity, packagePath).toEqual(expect.any(String)); - } - }); }); diff --git a/test/e2e/mock-parity.json b/test/e2e/mock-parity.json index 25d7feac17a..e593f4febb0 100644 --- a/test/e2e/mock-parity.json +++ b/test/e2e/mock-parity.json @@ -78,8 +78,7 @@ "src/lib/onboard/runtime-provider/podman-lifecycle.test.ts", "src/lib/onboard/runtime-provider/podman-preflight.test.ts", "src/lib/onboard/runtime-provider/podman.test.ts", - "test/e2e/support/podman-cpu-proof-workflow.test.ts", - "test/runtime-provider-source-shape.test.ts" + "test/e2e/support/podman-cpu-proof-workflow.test.ts" ] }, { diff --git a/test/e2e/support/base-image-publication-workflow-boundary.test.ts b/test/e2e/support/base-image-publication-workflow-boundary.test.ts index e62085704c4..a7094e1e1be 100644 --- a/test/e2e/support/base-image-publication-workflow-boundary.test.ts +++ b/test/e2e/support/base-image-publication-workflow-boundary.test.ts @@ -99,27 +99,6 @@ describe("base-image publication workflow boundary (#7372)", () => { expect(validate(value)).toEqual([]); }); - // source-shape-contract: security -- Immutable base contracts must outlive the qualification interval so later E2E cannot fall back to a mutable alias. - it("retains immutable base contracts for later qualification (#9049)", () => { - const action = YAML.parse( - fs.readFileSync( - path.join(process.cwd(), ".github/actions/publish-base-image-manifest/action.yaml"), - "utf8", - ), - ) as { runs: { steps: MutableStep[] } }; - const upload = action.runs.steps.find( - (step) => step.name === "Upload managed base image contract", - ); - - expect(upload).toMatchObject({ - uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a", - with: { - "if-no-files-found": "error", - "retention-days": 90, - }, - }); - }); - it.each([ ["push to main", "push", "", "1"], ["manual main", "workflow_dispatch", "", "1"], diff --git a/test/e2e/support/dockerhub-auth-workflow-boundary.test.ts b/test/e2e/support/dockerhub-auth-workflow-boundary.test.ts index 6c686f0dbd4..a5a21cc8bbe 100644 --- a/test/e2e/support/dockerhub-auth-workflow-boundary.test.ts +++ b/test/e2e/support/dockerhub-auth-workflow-boundary.test.ts @@ -150,61 +150,6 @@ function validateCleanupArtifactMutation(options: { } describe("shared Docker Hub authentication workflow boundary (#6961)", () => { - // source-shape-contract: security -- Immutable credential-bearing action bytes must stay bound to reviewed commit provenance. - it("binds the composite action and helper to their immutable reviewed revision (#6961)", () => { - expect(validateDockerHubAuthAction()).toEqual([]); - - const mappingErrors = validateAuthArtifactMutation({ - mutateAction: (action) => { - const runs = action.runs as { steps: WorkflowStep[] }; - runs.steps[0].env = { - DOCKERHUB_AUTH_REQUIRED: "${{ inputs.auth-required }}", - DOCKERHUB_USERNAME: "${{ inputs.token }}", - DOCKERHUB_TOKEN: "${{ inputs.username }}", - }; - runs.steps[0].run = "bash .github/scripts/docker-auth-setup.sh"; - }, - }); - expect(mappingErrors).toContain( - "docker-auth-setup action content must match the action reviewed at its immutable commit pin", - ); - expect(mappingErrors).toContain( - "docker-auth-setup action must preserve its exact three-input environment mapping and pinned helper invocation", - ); - - expect( - validateAuthArtifactMutation({ - mutateScript: (source) => `${source}# unreviewed drift\n`, - }), - ).toContain( - "docker-auth-setup script content must match the helper reviewed at its immutable commit pin", - ); - }); - - // source-shape-contract: security -- The cleanup action and helper content must remain bound to the pinned commit. - it("binds the cleanup action and helper content to the pinned commit", () => { - expect(validateDockerHubCleanupAction()).toEqual([]); - - const actionErrors = validateCleanupArtifactMutation({ - mutateAction: (action) => { - const runs = action.runs as { steps: WorkflowStep[] }; - runs.steps[0].run = "bash .github/scripts/docker-auth-cleanup.sh"; - }, - }); - expect(actionErrors).toContain( - "docker-auth-cleanup action content must match the pinned commit", - ); - expect(actionErrors).toContain( - "docker-auth-cleanup action must invoke the helper through github.action_path", - ); - - expect( - validateCleanupArtifactMutation({ - mutateScript: (source) => `${source}# unreviewed drift\n`, - }), - ).toContain("docker-auth-cleanup script content must match the pinned commit"); - }); - it( "accepts only the pinned pre-restore cleanup action in the complete workflow", () => { diff --git a/test/e2e/support/e2e-expected-state.test.ts b/test/e2e/support/e2e-expected-state.test.ts index 87a07bcfce9..879475a5ec2 100644 --- a/test/e2e/support/e2e-expected-state.test.ts +++ b/test/e2e/support/e2e-expected-state.test.ts @@ -16,19 +16,6 @@ import { listTargets } from "../registry/registry.ts"; import type { ExpectedState, StateProbeId } from "../registry/types.ts"; describe("typed expected-state registry behavior", () => { - // source-shape-contract: compatibility -- Registry indexing keeps every shipped expected-state selector resolvable - it("indexes every registered state by its unique id", () => { - const states = listExpectedStates(); - const ids = states.map((state) => state.id); - - expect(states.length).toBeGreaterThan(0); - expect(new Set(ids).size).toBe(ids.length); - for (const state of states) { - expect(getExpectedState(state.id)).toBe(state); - expect(requireExpectedState(state.id)).toBe(state); - } - }); - // source-shape-contract: compatibility -- Unknown expected-state selectors must retain actionable failure diagnostics it("rejects an unknown state with an actionable inventory", () => { const unknown = "synthetic-unknown-state"; @@ -117,105 +104,3 @@ describe("expected-state probe compilation", () => { expect(probesForState(state)).toEqual([]); }); }); - -describe("target expected-state references", () => { - // source-shape-contract: compatibility -- Every shipped target must resolve its expected-state runtime contract - it("resolves every state id consumed by the typed target registry", () => { - const referenced = listTargets() - .map((target) => target.expectedStateId) - .filter((id): id is string => id !== undefined); - - expect(referenced.length).toBeGreaterThan(0); - for (const id of new Set(referenced)) { - expect(getExpectedState(id), `expected_state '${id}' must resolve`).toBeDefined(); - } - }); - - // source-shape-contract: security -- Fail-closed targets must compile probes that forbid gateway and sandbox side effects - it("compiles fail-closed absence probes for targets that forbid runtime side effects", () => { - const failClosedTargets = listTargets().filter((target) => { - const forbidden = target.expectedFailure?.forbiddenSideEffects ?? []; - return forbidden.includes("gateway-started") && forbidden.includes("sandbox-created"); - }); - - expect(failClosedTargets.length).toBeGreaterThan(0); - for (const target of failClosedTargets) { - const probes = probesForState(requireExpectedState(target.expectedStateId!)); - expect(probes, target.id).toEqual( - expect.arrayContaining(["gateway-absent", "sandbox-absent"]), - ); - } - }); - - // source-shape-contract: security -- Every preflight failure must compile absence probes before privileged runtime creation - it("compiles absence probes for every preflight failure contract", () => { - const preflightFailures = listTargets().filter( - (target) => target.expectedFailure?.phase === "preflight", - ); - - expect(preflightFailures.length).toBeGreaterThan(0); - for (const target of preflightFailures) { - const probes = probesForState(requireExpectedState(target.expectedStateId!)); - expect(probes, target.id).toEqual( - expect.arrayContaining(["gateway-absent", "sandbox-absent"]), - ); - } - }); - - // source-shape-contract: security -- Policy-selection failures must stop before gateway or sandbox side effects - it("keeps policy-selection failures limited to the installed CLI", () => { - const policySelectionFailures = listTargets().filter( - (target) => target.expectedFailure?.errorClass === "policy-presets-required", - ); - - expect(policySelectionFailures.length).toBeGreaterThan(0); - for (const target of policySelectionFailures) { - expect(probesForState(requireExpectedState(target.expectedStateId!)), target.id).toEqual([ - "cli-installed", - ]); - } - }); - - // source-shape-contract: compatibility -- Terminal agent targets must not require an unsupported host gateway probe - it("omits host gateway probes for targets whose loaded agent runtime is terminal", () => { - const targetAgents = listTargets() - .filter((target) => target.manifestPath !== undefined) - .map((target) => ({ - target, - agent: loadAgent( - loadManifest(path.resolve(import.meta.dirname, "../../..", target.manifestPath!)).document - .spec.onboarding.agent, - ), - })); - const terminalTargets = targetAgents.filter(({ agent }) => agent.runtime?.kind === "terminal"); - - expect(targetAgents.length).toBe(listTargets().length); - expect(terminalTargets.length).toBeGreaterThan(0); - for (const { target } of terminalTargets) { - const probes = probesForState(requireExpectedState(target.expectedStateId!)); - expect(probes, target.id).toContain("cli-installed"); - expect(probes, target.id).toContain("sandbox-running"); - expect(probes, target.id).not.toContain("gateway-healthy"); - expect(probes, target.id).not.toContain("gateway-absent"); - } - }); - - // source-shape-contract: security -- Post-reboot targets must retain host preservation and gateway recovery probes - it("compiles gateway-health and host-preservation probes for every post-reboot recovery target", () => { - const recoveryTargets = listTargets().filter( - (target) => target.environment?.lifecycle === "post-reboot-recovery", - ); - - expect(recoveryTargets.length).toBeGreaterThan(0); - for (const target of recoveryTargets) { - const probes = probesForState(requireExpectedState(target.expectedStateId!)); - expect(probes, target.id).toEqual( - expect.arrayContaining([ - "gateway-healthy", - "local-registry-entry-present", - "docker-sandbox-container-present", - ]), - ); - } - }); -}); diff --git a/test/e2e/support/e2e-host-dependency-workflow-boundary.test.ts b/test/e2e/support/e2e-host-dependency-workflow-boundary.test.ts index ce8486388f6..9e41fc7a2dd 100644 --- a/test/e2e/support/e2e-host-dependency-workflow-boundary.test.ts +++ b/test/e2e/support/e2e-host-dependency-workflow-boundary.test.ts @@ -76,32 +76,6 @@ function writeExecutable(filePath: string, source: string): void { } describe("E2E host dependency action boundary (#6961)", () => { - // source-shape-contract: security -- Privileged apt host setup must stay bound to the reviewed immutable action provenance. - it("binds the host-dependency action and helper to their immutable reviewed revision (#6961)", () => { - expect(validateHostDependencyAction()).toEqual([]); - - const mappingErrors = validateActionMutation({ - mutateAction: (source) => { - const action = YAML.parse(source) as Record; - const runs = action.runs as { steps: Array> }; - runs.steps[0].env = { HOST_DEPENDENCY_PACKAGES: "${{ inputs.packages }} curl" }; - return YAML.stringify(action); - }, - }); - expect(mappingErrors).toContain( - "host-dependency-setup action content must match the action reviewed at its immutable commit pin", - ); - expect(mappingErrors).toContain( - "host-dependency-setup action must preserve its exact single-input package mapping and pinned helper invocation", - ); - - expect( - validateActionMutation({ mutateScript: (source) => `${source}# unreviewed drift\n` }), - ).toContain( - "host-dependency-setup script content must match the helper reviewed at its immutable commit pin", - ); - }); - it.each([ { jobName: "live", diff --git a/test/e2e/support/e2e-live-project-config.test.ts b/test/e2e/support/e2e-live-project-config.test.ts index 1edbb46e495..8563aa67eea 100644 --- a/test/e2e/support/e2e-live-project-config.test.ts +++ b/test/e2e/support/e2e-live-project-config.test.ts @@ -7,34 +7,8 @@ import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { describe, expect, it } from "vitest"; -import config from "../../../vitest.config.ts"; import { shouldRunInstallerIntegration, shouldRunLiveE2E } from "../fixtures/live-project-gate.ts"; -interface ProjectConfig { - test?: { - env?: Record; - fileParallelism?: boolean; - name?: string; - include?: string[]; - retry?: number; - setupFiles?: string[]; - }; -} - -interface RootConfig { - test?: { - env?: Record; - projects?: ProjectConfig[]; - }; -} - -const DRIFT_PREFLIGHT_BYPASS = "NEMOCLAW_DISABLE_GATEWAY_DRIFT_PREFLIGHT"; -const FIXTURE_UMASK_SETUP = "test/helpers/normalize-fixture-umask.ts"; - -function projectConfigs(): ProjectConfig[] { - return (config as RootConfig).test?.projects ?? []; -} - describe("gated E2E Vitest projects", () => { it("enables installer integration only in CI or with the installer opt-in env var", () => { expect(shouldRunInstallerIntegration({})).toBe(false); @@ -53,38 +27,6 @@ describe("gated E2E Vitest projects", () => { expect(shouldRunLiveE2E({ NEMOCLAW_RUN_LIVE_E2E: " TRUE " })).toBe(true); }); - it("keeps stateful E2E project retries disabled and aggregate live files serial (#6692)", () => { - const statefulProjects = projectConfigs().filter( - (project) => !project.test?.setupFiles?.includes(FIXTURE_UMASK_SETUP), - ); - const deterministicProjects = projectConfigs().filter((project) => - project.test?.setupFiles?.includes(FIXTURE_UMASK_SETUP), - ); - - expect(statefulProjects.length).toBeGreaterThan(0); - expect(statefulProjects.every((project) => project.test?.retry === 0)).toBe(true); - expect(statefulProjects.some((project) => project.test?.fileParallelism === false)).toBe(true); - expect(deterministicProjects.every((project) => project.test?.retry === undefined)).toBe(true); - }); - - // source-shape-contract: security -- Live projects must not inherit the deterministic drift-preflight bypass - it("keeps the drift-preflight bypass out of live projects (#6692)", () => { - const statefulProjects = projectConfigs().filter( - (project) => !project.test?.setupFiles?.includes(FIXTURE_UMASK_SETUP), - ); - const deterministicProjects = projectConfigs().filter((project) => - project.test?.setupFiles?.includes(FIXTURE_UMASK_SETUP), - ); - - expect((config as RootConfig).test?.env?.[DRIFT_PREFLIGHT_BYPASS]).toBeUndefined(); - for (const project of deterministicProjects) { - expect(project.test?.env?.[DRIFT_PREFLIGHT_BYPASS], project.test?.name).toBe("1"); - } - for (const project of statefulProjects) { - expect(project.test?.env?.[DRIFT_PREFLIGHT_BYPASS], project.test?.name).toBeUndefined(); - } - }); - it("cleans and rebuilds the CLI before aggregate live E2E execution (#6692)", () => { const npmCli = process.env.npm_execpath ?? ""; expect(npmCli).not.toBe(""); diff --git a/test/e2e/support/e2e-live-registry-discovery.test.ts b/test/e2e/support/e2e-live-registry-discovery.test.ts index e2a17f9d3cc..a2c362708d0 100644 --- a/test/e2e/support/e2e-live-registry-discovery.test.ts +++ b/test/e2e/support/e2e-live-registry-discovery.test.ts @@ -26,17 +26,6 @@ function syntheticTarget(environment: TargetEnvironment = SUPPORTED_ENVIRONMENT) } describe("live target registry discovery support", () => { - // source-shape-contract: compatibility -- Every shipped target must classify as runnable or expose a concrete skip reason - it("classifies every shipped target as supported or with a concrete reason", () => { - const targets = listTargets(); - - expect(targets.length).toBeGreaterThan(0); - for (const registered of targets) { - const support = liveTargetSupport(registered); - expect(support.supported || support.reasons.length > 0, registered.id).toBe(true); - } - }); - it("accepts a fully wired synthetic target and forwards its pending suites", () => { const registered = syntheticTarget(); diff --git a/test/e2e/support/e2e-live-skip-name-contract.test.ts b/test/e2e/support/e2e-live-skip-name-contract.test.ts index 85cda2a0015..0a1f6a7db81 100644 --- a/test/e2e/support/e2e-live-skip-name-contract.test.ts +++ b/test/e2e/support/e2e-live-skip-name-contract.test.ts @@ -29,26 +29,6 @@ function syntheticTarget(platform: string): TargetDefinition { * tests and Vitest would exit non-zero with no structured skip reason. */ describe("live registry-targets skip-name contract", () => { - // source-shape-contract: compatibility -- Live test registration names must remain addressable by stable target identifiers - it("registers every target under a name equal to its id", () => { - const targets = listTargets(); - expect(targets.length).toBeGreaterThan(0); - for (const target of targets) { - expect(liveTargetTestName(target)).toBe(target.id); - } - }); - - // source-shape-contract: compatibility -- Workflow target filters must select every registered live test by exact identifier - it('matches the workflow\'s exact `-t "^${TARGET_ID}$"` regex for every target', () => { - for (const target of listTargets()) { - const name = liveTargetTestName(target); - const filter = new RegExp(`^${target.id}$`); - expect(filter.test(name), `workflow filter must match registered name for ${target.id}`).toBe( - true, - ); - } - }); - it("keeps a synthetically unsupported target selectable under its exact id", () => { const unsupported = syntheticTarget("synthetic-unwired-platform"); const support = liveTargetSupport(unsupported); diff --git a/test/e2e/support/e2e-manifests.test.ts b/test/e2e/support/e2e-manifests.test.ts index 387e1ded150..8420d8649b9 100644 --- a/test/e2e/support/e2e-manifests.test.ts +++ b/test/e2e/support/e2e-manifests.test.ts @@ -53,17 +53,4 @@ describe("NemoClawInstance manifests", () => { ); }); - // source-shape-contract: compatibility -- Every shipped target path must load through the validated E2E manifest consumer - it("resolves every typed target manifest path to a validated manifest", () => { - const manifestPaths = new Set( - loadManifestsFromDir(MANIFEST_DIR).map((manifest) => path.resolve(manifest.filePath)), - ); - const missingManifests = listTargets() - .map((target) => target.manifestPath) - .filter((manifestPath): manifestPath is string => Boolean(manifestPath)) - .map((manifestPath) => path.resolve(REPO_ROOT, manifestPath)) - .filter((manifestPath) => !manifestPaths.has(manifestPath)); - - expect(missingManifests, `missing manifest files: ${missingManifests.join(", ")}`).toEqual([]); - }); }); diff --git a/test/e2e/support/e2e-matrix.test.ts b/test/e2e/support/e2e-matrix.test.ts index e22da178ca5..f0384856b1a 100644 --- a/test/e2e/support/e2e-matrix.test.ts +++ b/test/e2e/support/e2e-matrix.test.ts @@ -83,30 +83,6 @@ describe("live E2E target matrix", () => { expect(() => resolveRunnerForTarget(broken)).toThrow(/no default for platform/); }); - // source-shape-contract: compatibility -- Default live matrix output must cover every fixture-supported registered target once - it("builds the default live matrix from every fixture-supported target", () => { - const targets = listTargets(); - const supportedTargets = targets.filter((entry) => liveTargetSupport(entry).supported); - const matrix = buildLiveTargetMatrix(); - - expect(matrix).not.toHaveLength(0); - expect(matrix.map((entry) => entry.id)).toEqual(supportedTargets.map((entry) => entry.id)); - expect(new Set(matrix.map((entry) => entry.id)).size).toBe(matrix.length); - for (const entry of matrix) { - const registered = supportedTargets.find((target) => target.id === entry.id); - expect( - registered, - `matrix entry '${entry.id}' must resolve to a supported target`, - ).toBeDefined(); - expect(entry).toMatchObject({ - runner: resolveRunnerForTarget(registered!).runner, - supported: true, - supportReasons: [], - pendingRuntimeSuites: registered!.suiteIds ?? [], - }); - } - }); - it("keeps explicitly selected unsupported live targets in the matrix with skip reasons", () => { const unsupported = requireUnsupportedTarget(); const support = liveTargetSupport(unsupported); diff --git a/test/e2e/support/e2e-semantic-phase-check.test.ts b/test/e2e/support/e2e-semantic-phase-check.test.ts index 05b402143e6..315ded92e34 100644 --- a/test/e2e/support/e2e-semantic-phase-check.test.ts +++ b/test/e2e/support/e2e-semantic-phase-check.test.ts @@ -101,23 +101,6 @@ describe("semantic E2E phase checker", () => { ]); }); - // source-shape-contract: compatibility -- Generated policy output must precede semantic collection and remain shared with the canonical CLI build - test("builds the policy boundary before semantic collection and CLI compilation", () => { - const scripts = ( - JSON.parse(fs.readFileSync(path.join(REPO_ROOT, "package.json"), "utf8")) as { - scripts: Record; - } - ).scripts; - - expect(scripts["build:policy-boundary"]).toBe("tsc -p nemoclaw/tsconfig.shared.json"); - expect(scripts["test:e2e-phases:check"]).toMatch( - /^npm run build:policy-boundary && node .*tools\/e2e\/check-semantic-phases\.mts$/u, - ); - expect(scripts["build:cli"]).toMatch( - /^npm run build:policy-boundary && tsc -p tsconfig\.src\.json &&/u, - ); - }); - test("derives coverage from registry, free-standing, shared, and forwarding workflow paths", () => { const modules = semanticPhaseCoverageModules( { diff --git a/test/e2e/support/podman-cpu-proof-workflow.test.ts b/test/e2e/support/podman-cpu-proof-workflow.test.ts index b9f972f9214..7183308afd4 100644 --- a/test/e2e/support/podman-cpu-proof-workflow.test.ts +++ b/test/e2e/support/podman-cpu-proof-workflow.test.ts @@ -360,108 +360,6 @@ function withProofFixture(run: (fixture: ProofFixture) => void): void { } } describe("native Podman CPU proof workflow", () => { - // source-shape-contract: security -- Checkout binding and package pins bind the credential-free Podman proof to the commit under review and its runtime bytes - it("runs as a credential-free PR workflow bound to the commit under review", () => { - const parsed = workflow(); - const job = proofJob(); - expect(parsed.permissions).toEqual({ contents: "read" }); - expect(parsed.on.pull_request.types).toEqual(["opened", "synchronize", "reopened"]); - expect(parsed.on.pull_request.paths).toEqual( - expect.arrayContaining([ - "src/lib/adapters/podman/**", - "src/lib/onboard/docker-driver-gateway-*.ts", - "src/lib/onboard/managed-bootstrap/podman-*.ts", - "src/lib/onboard/experimental/portable-demo-lifecycle.ts", - "src/lib/onboard/runtime-provider/container-state-mutation.ts", - "src/lib/onboard/runtime-provider/docker-state-mutation.ts", - "src/lib/onboard/experimental/portable-cpu-delegation-preflight*.ts", - "src/lib/onboard/experimental/portable-host-preparation*.ts", - "scripts/install-openshell.sh", - "test/e2e/live/podman-cpu-lifecycle-artifacts.ts", - "test/e2e/live/podman-cpu-lifecycle-helpers.ts", - "test/e2e/live/podman-cpu-lifecycle-policy.yaml", - "test/e2e/registry/native-runtime-qualification.ts", - "test/e2e/live/portable-cpu-delegation-proof.test.ts", - ]), - ); - expect(job.name).toBe("Rootless Podman CPU lifecycle with Docker disabled"); - expect(job["runs-on"]).toBe("ubuntu-26.04"); - expect(job["timeout-minutes"]).toBe(30); - expect(job.env?.NEMOCLAW_RUN_LIVE_E2E).toBe("1"); - expect(job.env?.E2E_SOURCE_REVISION).toBe("${{ github.event.pull_request.head.sha }}"); - expect(job.env?.NEMOCLAW_OPENSHELL_PIN_VERSION).toBe("0.0.101"); - expect(job.env?.PODMAN_APT_VERSION).toBe("5.7.0+ds2-3build1"); - expect(namedStep("Checkout").with).toMatchObject({ - ref: "${{ github.event.pull_request.head.sha }}", - }); - expect(namedStep("Build shared sandbox-name contract").run).toBe( - "npm run build:policy-boundary", - ); - const installPodman = namedStep("Install Podman 5 runtime").run ?? ""; - expect(installPodman).toContain("apt-get install --yes"); - expect(installPodman).toContain("passt"); - expect(installPodman).toContain("uidmap"); - expect(installPodman).toContain('"podman=$PODMAN_APT_VERSION"'); - expect(installPodman).toContain('test "$package_version" = "$PODMAN_APT_VERSION"'); - expect(installPodman).toContain('test "$version" = "podman version 5.7.0"'); - const installOpenShell = namedStep("Install pinned OpenShell runtime").run ?? ""; - expect(installOpenShell).toContain("env -u GH_TOKEN -u GITHUB_TOKEN"); - expect(installOpenShell).toContain("bash scripts/install-openshell.sh"); - expect(installOpenShell).toContain("$HOME/.local/bin"); - expect(readRepoText(".github/workflows/podman-cpu-proof.yaml")).not.toContain("${{ secrets."); - const delegation = delegationJob(); - const modeCommand = (mode: PortableCpuDelegationProofMode) => - `node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts ${mode}`; - expect(parsed.on.pull_request.paths).toContain( - "scripts/checks/run-portable-cpu-delegation-proof.mts", - ); - const proofScript = readRepoText("scripts/checks/run-portable-cpu-delegation-proof.mts"); - expect(proofScript).toContain("shell: false"); - expect(proofScript).not.toContain("shell: true"); - expect(proofScript).not.toContain("execSync("); - expect(proofScript).not.toContain("eval("); - expect(delegation.name).toBe("Portable CPU delegation admission on Ubuntu 22.04"); - expect(delegation["runs-on"]).toBe("ubuntu-22.04"); - expect(delegation["timeout-minutes"]).toBe(15); - expect(delegation.env?.E2E_CPU_DELEGATION_USER).toBe("nemoclaw-e2e"); - expect(delegation.env?.E2E_TARGET_ID).toBe("portable-cpu-delegation"); - expect(delegation.env?.E2E_SOURCE_REVISION).toBe("${{ github.event.pull_request.head.sha }}"); - expect(delegation.env?.NEMOCLAW_RUN_LIVE_E2E).toBe("1"); - expect(namedDelegationStep("Checkout").with).toMatchObject({ - "persist-credentials": false, - ref: "${{ github.event.pull_request.head.sha }}", - }); - expect(namedDelegationStep("Build shared sandbox-name contract").run).toBe( - "npm run build:policy-boundary", - ); - expect( - namedDelegationStep("Prepare system and app slice CPU settings without service delegation") - .run, - ).toBe(modeCommand("prepare")); - expect( - namedDelegationStep( - "Verify missing delegation blocks portable configuration and service activation", - ).run, - ).toBe(modeCommand("reject")); - expect(namedDelegationStep("Apply administrator delegation and prove admission").run).toBe( - modeCommand("admit"), - ); - const diagnostics = namedDelegationStep("Capture CPU delegation failure diagnostics"); - expect(diagnostics.if).toBe("failure()"); - expect(diagnostics.run).toBe(modeCommand("diagnostics")); - const cleanup = namedDelegationStep("Restore the user manager boundary"); - expect(cleanup.if).toBe("always()"); - expect(cleanup.run).toBe(modeCommand("cleanup")); - const delegationProof = readRepoText("test/e2e/live/portable-cpu-delegation-proof.test.ts"); - expect(delegationProof).toContain('from "../fixtures/e2e-test.ts"'); - expect(delegationProof).not.toContain('from "vitest"'); - expect(delegationProof).toContain('"rev-parse", "HEAD"'); - expect(delegationProof).toContain("e2ePhases"); - expect(delegationProof).toContain("process.env.E2E_CPU_DELEGATION_STATE"); - expect(delegationProof).toContain("process.getuid?.()"); - expect(delegationProof).not.toContain("process.argv"); - expect(delegationProof).not.toContain("main();"); - }); it("executes the five typed proof modes with exact argv and durable cleanup receipts (#9188)", () => { withProofFixture((fixture) => { const modes: readonly PortableCpuDelegationProofMode[] = [ diff --git a/test/e2e/support/same-commit-reliability.test.ts b/test/e2e/support/same-commit-reliability.test.ts index 696c98735da..693461e2ee3 100644 --- a/test/e2e/support/same-commit-reliability.test.ts +++ b/test/e2e/support/same-commit-reliability.test.ts @@ -168,35 +168,6 @@ describe("same-commit E2E reliability", () => { expect(report).not.toContain(secret); }); - // source-shape-contract: security -- The reliability reporter must execute only from the trusted default-branch controller while authenticating the canonical E2E source repository and branch - it("locks the reporter to canonical source and trusted controller identities (#9168)", () => { - type RetryWorkflow = { - jobs: { "report-same-commit-reliability": WorkflowJob }; - }; - const reporter = - readYaml(RETRY_WORKFLOW_PATH).jobs["report-same-commit-reliability"]; - const guard = reporter.if ?? ""; - for (const fragment of [ - "github.repository == 'NVIDIA/NemoClaw'", - "github.event.workflow_run.path == '.github/workflows/e2e.yaml'", - "github.event.workflow_run.head_branch == 'main'", - "github.event.workflow_run.head_repository.full_name == 'NVIDIA/NemoClaw'", - ]) { - expect(guard).toContain(fragment); - } - expect(workflowStep(reporter, "Checkout trusted reliability reporter").with).toEqual({ - ref: "${{ github.workflow_sha }}", - "persist-credentials": false, - }); - const build = workflowStep(reporter, "Build advisory same-commit reliability report"); - expect(build.env).toEqual({ - GITHUB_TOKEN: "${{ github.token }}", - SOURCE_RUN_ID: "${{ github.event.workflow_run.id }}", - }); - expect(build.run).toContain('>"${RUNNER_TEMP}/same-commit-reliability.json"'); - expect(build.run).toContain('2>"${RUNNER_TEMP}/same-commit-reliability.md"'); - }); - it("consumes dispatch, retry, and runner classifications without retaining payload text", async () => { const secret = "sk-live-secret-output"; const dispatch = artifactZip([ diff --git a/test/fetch-guard-patch-regression.test.ts b/test/fetch-guard-patch-regression.test.ts index 6dcdd43d62f..41935d31d2e 100644 --- a/test/fetch-guard-patch-regression.test.ts +++ b/test/fetch-guard-patch-regression.test.ts @@ -436,34 +436,6 @@ describe("fetch-guard patch regression guard", () => { ).toContain("rm -rf /usr/local/lib/node_modules/mcporter /usr/local/bin/mcporter"); }); - // source-shape-contract: security -- Cross-file OpenClaw pins bind reviewed classifiers to verified package integrity - it("requires classifier review and integrity evidence when the OpenClaw build pin changes", () => { - const reviewMessage = - "Update fetch-guard classifier expectations before changing the OpenClaw build version."; - - const blueprintMinVersion = readBlueprintMinOpenClawVersion(); - const baseImageVersion = readDockerfileBaseOpenClawVersion(); - const runtimeVersion = readDockerfileOpenClawVersion(); - - expectVersionAtLeast( - baseImageVersion, - blueprintMinVersion, - "Dockerfile.base OpenClaw target must satisfy the blueprint minimum.", - ); - expect( - runtimeVersion, - "Dockerfile and Dockerfile.base must build the same OpenClaw target.", - ).toBe(baseImageVersion); - expect(readDockerfileBaseOpenClawIntegrity()).toBe(EXPECTED_OPENCLAW_INTEGRITY); - expect(readDockerfileOpenClawIntegrity()).toBe(EXPECTED_OPENCLAW_INTEGRITY); - expect([...REVIEWED_OPENCLAW_PATCH_CLASSIFIER_VERSIONS], reviewMessage).toContain( - runtimeVersion, - ); - expect([...REVIEWED_OPENCLAW_PATCH_CLASSIFIER_VERSIONS], reviewMessage).toContain( - baseImageVersion, - ); - }); - it("applies the Dockerfile OpenClaw compatibility patch block to executable fixtures", async () => { const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-openclaw-patches-")); const dist = path.join(tmp, "dist"); diff --git a/test/hermes-final-image-layout.test.ts b/test/hermes-final-image-layout.test.ts index 34b08e33cbb..6d38b504a3a 100644 --- a/test/hermes-final-image-layout.test.ts +++ b/test/hermes-final-image-layout.test.ts @@ -228,325 +228,6 @@ describe("Hermes final image layout", () => { expect(hasBuildKitRunMount(dockerfile)).toBe(expected); }); - // source-shape-contract: compatibility -- Legacy-compatible grouped payload copies preserve the measured Hermes layer budget without invalidating earlier build work - it("uses grouped legacy-compatible payload layers at their cache boundaries (#7611)", () => { - const dockerfile = fs.readFileSync(HERMES_DOCKERFILE, "utf-8"); - const doctorLayer = dockerRunCommandBetween( - dockerfile, - "# Run Hermes' upstream repair", - "# Install NemoClaw plugin into Hermes", - ); - const stages = dockerfile.split(/(?=^FROM )/mu).filter((stage) => stage.startsWith("FROM ")); - const finalStageIndex = stages.findIndex((stage) => stage.startsWith("FROM ${BASE_IMAGE}")); - const finalStage = stages[finalStageIndex] ?? ""; - const payloads = [ - { - stage: "hermes-npm-patch-payload", - copies: [ - "COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts", - "COPY scripts/patch-bundled-npm-brace-expansion.mts /scripts/patch-bundled-npm-brace-expansion.mts", - "COPY scripts/lib/patch-bundled-npm-ip-address.mts /scripts/lib/patch-bundled-npm-ip-address.mts", - "COPY scripts/patch-bundled-npm-tar.mts /scripts/patch-bundled-npm-tar.mts", - "COPY agents/hermes/security-dependencies.patch /scripts/hermes-security-dependencies.patch", - ], - }, - { - stage: "hermes-agent-payload", - copies: [ - "COPY agents/hermes/plugin/ /opt/nemoclaw-hermes-plugin/", - "COPY agents/hermes/generate-config.ts /opt/nemoclaw-hermes-config/generate-config.ts", - "COPY agents/hermes/config/ /opt/nemoclaw-hermes-config/config/", - "COPY agents/hermes/image-build-probes.py /opt/nemoclaw-hermes-config/image-build-probes.py", - "COPY agents/hermes/patch-gateway-runtime-metadata.py /opt/nemoclaw-hermes-config/patch-gateway-runtime-metadata.py", - "COPY agents/hermes/patch-gateway-process-identity.py /opt/nemoclaw-hermes-config/patch-gateway-process-identity.py", - "COPY agents/hermes/patch-cron-execution-runtime.py /opt/nemoclaw-hermes-config/patch-cron-execution-runtime.py", - "COPY agents/hermes/patch-cron-restore-drain.py /opt/nemoclaw-hermes-config/patch-cron-restore-drain.py", - "COPY agents/hermes/patch-neutral-platform-env-activation.py /opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py", - "COPY agents/hermes/host/managed-tool-gateway-matrix.json /opt/nemoclaw-hermes-config/managed-tool-gateway-matrix.json", - "COPY src/lib/hermes-managed-route.ts /src/lib/hermes-managed-route.ts", - "COPY src/lib/tool-disclosure.ts /src/lib/tool-disclosure.ts", - "COPY src/lib/messaging/ /src/lib/messaging/", - "COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts", - ], - }, - { - stage: "hermes-runtime-payload", - copies: [ - "COPY --from=mcp-tool-discovery-runtime /opt/mcp-tool-discovery-runtime/dist/ /usr/local/lib/nemoclaw/mcp-tool-discovery-runtime/", - "COPY nemoclaw-blueprint/ /opt/nemoclaw-blueprint/", - "COPY scripts/lib/sandbox-init.sh /usr/local/lib/nemoclaw/sandbox-init.sh", - "COPY scripts/lib/entrypoint-env-wrapper.sh /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh", - "COPY scripts/lib/gateway-supervisor.sh /usr/local/lib/nemoclaw/gateway-supervisor.sh", - "COPY scripts/lib/sandbox-rlimits.sh /usr/local/lib/nemoclaw/sandbox-rlimits.sh", - "COPY agents/hermes/start.sh /usr/local/bin/nemoclaw-start", - "COPY scripts/managed-startup-hold.sh /usr/local/bin/nemoclaw-managed-startup-hold", - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/bin/nemoclaw-managed-bootstrap /usr/local/bin/nemoclaw-managed-bootstrap", - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh /usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh", - "COPY --from=managed-startup-runtime-builder /out/managed-startup-image-runtime.cjs /usr/local/lib/nemoclaw/managed-startup-image-runtime.cjs", - "COPY scripts/gateway-control.sh /usr/local/bin/nemoclaw-gateway-control", - "COPY scripts/managed-gateway-control.py /usr/local/lib/nemoclaw/managed-gateway-control.py", - "COPY agents/hermes/validate-env-secret-boundary.py /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py", - "COPY agents/hermes/patch-session-list-preview.py /usr/local/lib/nemoclaw/patch-hermes-session-list-preview.py", - "COPY agents/hermes/patch-hermes-sqlite-temp-store.py /usr/local/lib/nemoclaw/patch-hermes-sqlite-temp-store.py", - "COPY agents/hermes/patch-discord-recovery-permissions.py /usr/local/lib/nemoclaw/patch-hermes-discord-recovery-permissions.py", - "COPY agents/hermes/patch-profile-policy-defaults.py /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py", - "COPY agents/hermes/managed_policy.py /usr/local/lib/nemoclaw/managed_policy.py", - "COPY agents/hermes/patch-langfuse-credentials.mts /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts", - "COPY agents/hermes/seed-dashboard-config.py /usr/local/lib/nemoclaw/seed-hermes-dashboard-config.py", - "COPY agents/hermes/runtime-config-guard.py /usr/local/lib/nemoclaw/hermes-runtime-config-guard.py", - "COPY agents/hermes/finalize-tirith-marker.py /usr/local/lib/nemoclaw/finalize-tirith-marker.py", - "COPY agents/hermes/build-mcp-digest.py /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py", - "COPY agents/hermes/mcp-config-transaction.py /usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py", - "COPY agents/hermes/cron-restore-control.py /usr/local/lib/nemoclaw/hermes-cron-restore-control.py", - "COPY src/lib/actions/sandbox/openshell-child-visible-credentials.v0.0.101.json /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.101.json", - "COPY scripts/state-dir-guard.py /usr/local/lib/nemoclaw/state-dir-guard.py", - "COPY scripts/runtime-state-mutation-control.py /usr/local/lib/nemoclaw/runtime-state-mutation-control.py", - "COPY scripts/runtime-state-mutation-startup-gate.py /usr/local/lib/nemoclaw/runtime-state-mutation-startup-gate.py", - "COPY scripts/runtime_state_mutation_hermes_publisher.py /usr/local/lib/nemoclaw/runtime_state_mutation_hermes_publisher.py", - "COPY agents/hermes/state-lock-plan.json /usr/local/share/nemoclaw/state-lock-plan.json", - "COPY agents/hermes/runtime-state-mutation-publisher-v1.json /usr/local/share/nemoclaw/runtime-state-mutation-publisher-v1.json", - "COPY nemoclaw-blueprint/scripts/*.js /usr/local/lib/nemoclaw/preloads/", - ], - }, - { - stage: "hermes-wrapper-payload", - copies: [ - "COPY agents/hermes/hermes-wrapper.py /usr/local/lib/nemoclaw/hermes-wrapper.py", - "COPY agents/hermes/validate-cli-adapter.py /usr/local/lib/nemoclaw/validate-hermes-cli-adapter.py", - "COPY agents/hermes/hermes-cli-adapter-v1.json /usr/local/share/nemoclaw/hermes-cli-adapter-v1.json", - ], - }, - ] as const; - const npmPatchCopy = "COPY --from=hermes-npm-patch-payload / /"; - const agentCopy = "COPY --from=hermes-agent-payload / /"; - const runtimeCopy = "COPY --from=hermes-runtime-payload / /"; - const wrapperCopy = "COPY --from=hermes-wrapper-payload / /"; - - expect(finalStageIndex).toBe(stages.length - 1); - expect(buildKitRunMountOptions(dockerfile)).toEqual([ - "--network=none --mount=from=hermes-managed-teams-wheels,target=/opt/nemoclaw-hermes-teams-wheels,ro", - ]); - expectManagedBootstrapNativeImageContract(dockerfile); - for (const payload of payloads) { - const stage = stages.find((entry) => entry.startsWith(`FROM scratch AS ${payload.stage}`)); - expect(stage?.match(/^COPY\b.*$/gmu)).toEqual(payload.copies); - expect(finalStage).toContain(`COPY --from=${payload.stage} / /`); - } - expect(finalStage.match(/^COPY\b.*$/gmu)).toEqual([ - npmPatchCopy, - agentCopy, - runtimeCopy, - wrapperCopy, - ]); - const npmPatch = indexOfRequired(finalStage, npmPatchCopy); - const agent = indexOfRequired(finalStage, agentCopy); - const runtime = indexOfRequired(finalStage, runtimeCopy); - const wrapper = indexOfRequired(finalStage, wrapperCopy); - const tarPatch = requireSingleReviewedDockerfileRunCommand( - finalStage, - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", - NPM_ROOT_ARGUMENTS, - ).commandStart; - const certifiInstall = indexOfRequired(finalStage, "RUN _hermes_certifi="); - const agentChmod = indexOfRequired( - finalStage, - "RUN chmod -R a+rX /opt/nemoclaw-hermes-plugin/", - ); - const managedMessagingUnionInstall = indexOfRequired( - finalStage, - "--agent hermes --phase managed-image-capability-union", - ); - expect(finalStage).toContain("UV_OFFLINE=true UV_FIND_LINKS=/opt/nemoclaw-hermes-teams-wheels"); - expect(dockerfile).toContain("FROM scratch AS hermes-managed-teams-0-wheels"); - expect(dockerfile).toContain( - "FROM hermes-managed-teams-${TARGETARCH}-wheels AS hermes-managed-teams-1-wheels", - ); - expect(dockerfile).toContain( - "FROM hermes-managed-teams-${NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION}-wheels AS hermes-managed-teams-wheels", - ); - expect( - indexOfRequired(dockerfile, "ARG NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0"), - ).toBeLessThan(indexOfRequired(dockerfile, "FROM scratch AS mcp-tool-discovery-runtime")); - for (const wheelSha256 of [ - "db16f714ec658b592929c6386a29792e90bb73840732f8ae65a198cda1fea96c", - "0072ffe68863a4c62818a4e631a186f092a4f09dfda74d1d4713415bac5d202d", - "e2b0257d9b8782830df61eb6aa993a1ddc0349daddd845739da45d2a29a0c44b", - "c61057695b9f1a97de9b6f54f0c66206903f56c22427b0bca31e0fc34da49311", - "dd17e95a7c71bce75e8108113438ba7c4a086b3bcad4f57a8c09b7af3d753c2d", - "10e481880b307a6a438c1cc7b0a1fa8754247239ef5a2e8fe82bd8a1e76e7682", - "e05da5bc73a3e026f962a223672002934c0f415064b6e2c3db0b255e46c7b521", - ]) { - expect(dockerfile).toContain(`--checksum=sha256:${wheelSha256}`); - } - const cronRestoreDrainPatch = indexOfRequired( - finalStage, - "ARG NEMOCLAW_HERMES_CRON_RESTORE_DRAIN_PATCHER_SHA256=", - ); - const profilePolicyPatch = indexOfRequired( - finalStage, - "RUN /usr/bin/python3 -I /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py", - ); - const neutralPlatformPatch = indexOfRequired( - finalStage, - "ARG NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256=", - ); - const neutralMessagingConfig = indexOfRequired(finalStage, "neutral-platform-inertness"); - const configFind = indexOfRequired(finalStage, "RUN find /opt/nemoclaw-hermes-config"); - const blueprintChmod = indexOfRequired( - finalStage, - "RUN chmod -R a+rX /opt/nemoclaw-blueprint/", - ); - const managedRuntimeDirectory = indexOfRequired( - finalStage, - "&& install -d -o root -g root -m 0755 /run/nemoclaw", - ); - const runtimeModeReplay = indexOfRequired( - finalStage, - "RUN chmod 755 /usr/local/bin/nemoclaw-start", - ); - const tirithFinalizerHash = indexOfRequired( - finalStage, - '"$NEMOCLAW_HERMES_TIRITH_FINALIZER_SHA256"', - ); - const pythonCheck = indexOfRequired(finalStage, "RUN test -x /usr/bin/python3"); - const darwinCompatibility = indexOfRequired( - finalStage, - 'RUN if [ "$NEMOCLAW_DARWIN_VM_COMPAT" = "1" ]', - ); - const metadataCheck = indexOfRequired(finalStage, "RUN check_metadata()"); - const modeNormalize = indexOfRequired(finalStage, "RUN chmod 755 \\"); - - expect(npmPatch).toBeLessThan(tarPatch); - expect(agent).toBeGreaterThan(certifiInstall); - expect(agent).toBeLessThan(agentChmod); - expect(cronRestoreDrainPatch).toBeLessThan(profilePolicyPatch); - expect(profilePolicyPatch).toBeLessThan(neutralPlatformPatch); - expect(neutralPlatformPatch).toBeLessThan(neutralMessagingConfig); - expect(managedMessagingUnionInstall).toBeLessThan(neutralMessagingConfig); - expect(runtime).toBeGreaterThan(configFind); - expect(runtime).toBeLessThan(managedRuntimeDirectory); - expect(managedRuntimeDirectory).toBeLessThan(blueprintChmod); - expect(runtime).toBeLessThan(blueprintChmod); - expect(managedRuntimeDirectory).toBeLessThan(runtimeModeReplay); - expect(finalStage).toContain("/usr/local/bin/nemoclaw-managed-bootstrap"); - expect(dockerfile).toContain( - "COPY tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle /out/managed-startup-image-runtime.cjs", - ); - expect(dockerfile).not.toContain( - "COPY src/lib/onboard/managed-bootstrap/ ./src/lib/onboard/managed-bootstrap/", - ); - expect(wrapper).toBeGreaterThan(tirithFinalizerHash); - expect(wrapper).toBeLessThan(pythonCheck); - expect(modeNormalize).toBeGreaterThan(darwinCompatibility); - expect(modeNormalize).toBeLessThan(metadataCheck); - for (const metadataContract of [ - "/scripts/patch-bundled-npm-brace-expansion.mts 'root:root 444'", - "/scripts/lib/patch-bundled-npm-ip-address.mts 'root:root 444'", - "/scripts/patch-bundled-npm-tar.mts 'root:root 444'", - "/opt/nemoclaw-hermes-config/generate-config.ts 'root:root 444'", - "/usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py 'root:root 755'", - "/usr/local/lib/nemoclaw/patch-hermes-discord-recovery-permissions.py 'root:root 755'", - "/usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py 'root:root 755'", - "/usr/local/lib/nemoclaw/managed_policy.py 'root:root 444'", - "/usr/local/share/nemoclaw/hermes-managed-policy.json 'root:root 444'", - "/usr/local/bin/nemoclaw-managed-bootstrap 'root:root 755'", - "/usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh 'root:root 444'", - "/usr/local/bin/nemoclaw-gateway-control 'root:root 700'", - "/usr/local/lib/nemoclaw/hermes-cron-restore-control.py 'root:root 700'", - "/sandbox/.nemoclaw 'root:root 1755'", - "/usr/local/share/nemoclaw/state-lock-plan.json 'root:root 444'", - "/usr/local/lib/nemoclaw/runtime-state-mutation-control.py 'root:root 500'", - "/usr/local/lib/nemoclaw/runtime-state-mutation-startup-gate.py 'root:root 555'", - "/usr/local/lib/nemoclaw/runtime_state_mutation_hermes_publisher.py 'root:root 500'", - "/var/lib/nemoclaw/runtime-state-mutation 'root:root 711'", - "/run/nemoclaw/runtime-state-mutation-startup 'root:root 711'", - "/usr/local/share/nemoclaw/runtime-state-mutation-publisher-v1.json 'root:root 444'", - "/usr/local/lib/nemoclaw/preloads/sandbox-safety-net.js 'root:root 444'", - "/usr/local/lib/nemoclaw/hermes-wrapper.py 'root:root 755'", - "/usr/local/lib/nemoclaw/validate-hermes-cli-adapter.py 'root:root 755'", - "/usr/local/share/nemoclaw/hermes-cli-adapter-v1.json 'root:root 444'", - ]) { - expect(finalStage).toContain(`check_metadata ${metadataContract}`); - } - expect(finalStage).toContain("/opt/hermes/.venv/bin/python3 -I -c 'import runpy, yaml;"); - expect(finalStage).toContain( - 'runpy.run_path("/usr/local/lib/nemoclaw/runtime-state-mutation-control.py"', - ); - expect(finalStage).toContain( - 'runpy.run_path("/usr/local/lib/nemoclaw/runtime_state_mutation_hermes_publisher.py"', - ); - expect(finalStage).toContain( - 'runpy.run_path("/usr/local/lib/nemoclaw/runtime-state-mutation-startup-gate.py"', - ); - expect(doctorLayer).toContain( - "HERMES_HOME=/sandbox/.hermes /usr/local/bin/hermes doctor --fix", - ); - expect(doctorLayer).toContain('if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then'); - expect(doctorLayer).toContain('assert m.version("microsoft-teams-apps") == "2.0.13.4"'); - expect(doctorLayer).toContain('assert m.version("aiohttp") == "3.14.3"'); - expect(doctorLayer).toContain("assert len(neutral) == 30"); - expect(finalStage).toContain("neutral-platform-inertness"); - expect(finalStage).toContain("GOOGLE_CHAT_SERVICE_ACCOUNT_JSON"); - expect(finalStage).toContain("WHATSAPP_CLOUD_ACCESS_TOKEN"); - expect(finalStage).toContain( - "ARG NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256=" + - "b50a8390311c828fa9e13084e9af0caadafe2380ae161ef36dd4bdf792b22ee6", - ); - expect(finalStage).toContain( - "ARG NEMOCLAW_HERMES_NEUTRAL_PLATFORM_OUTPUT_SHA256=" + - "77ad342af30d59a5b863d9f5f817247d816fd582fb12d38e074243f88d85b9f4", - ); - expect(doctorLayer).toMatch(/generate-config[.]ts\s+&& if /u); - expect(doctorLayer).toMatch(/fi\s+&& rm -rf \/sandbox\/[.]cache$/u); - expect(finalStage).toContain("check_absent /opt/hermes/tests \\"); - expect(finalStage).toContain( - "&& check_absent /opt/nemoclaw-hermes-config/image-build-probes.py \\", - ); - expect(finalStage).toContain( - "&& check_absent /sandbox/.nemoclaw/hermes-cron-restore-drain.json \\", - ); - expect(finalStage).toContain( - "&& check_absent /sandbox/.nemoclaw/hermes-cron-restore-release-recovery.json \\", - ); - expect(finalStage).toContain("&& check_absent /sandbox/.cache \\"); - expect(finalStage).toContain("&& check_absent /sandbox/.hermes/managed-policy.json \\"); - expect(finalStage).toContain("RUN chown root:root /sandbox/.nemoclaw \\"); - expect(finalStage).toContain("&& chmod 1755 /sandbox/.nemoclaw \\"); - expect(finalStage).toContain("&& chown sandbox:sandbox /sandbox/.nemoclaw/config.json"); - }); - - // source-shape-contract: security -- Exact source-to-image digests keep the reviewed Hermes runtime entrypoints bound to the files copied into the sandbox image - it("keeps security entrypoint hashes synchronized with the copied files", () => { - const dockerfile = fs.readFileSync(HERMES_DOCKERFILE, "utf-8"); - - for (const entry of HERMES_INTEGRITY_FILES) { - const digest = createHash("sha256") - .update(fs.readFileSync(path.join(ROOT, entry.source))) - .digest("hex"); - const declaredDigest = dockerfile.match( - new RegExp(`^ARG ${entry.arg}=([0-9a-f]{64})$`, "mu"), - )?.[1]; - - expect(dockerfile).toContain(`COPY ${entry.source} ${entry.target}`); - expect(declaredDigest, `${entry.arg} must match ${entry.source}`).toBe(digest); - expect(dockerfile).toContain(`"$${entry.arg}" ${entry.target}`); - } - }); - - // source-shape-contract: security -- Adapter bytes must pass their committed integrity gate before the image build executes validator code - it("verifies CLI adapter integrity before executing its validator", () => { - const dockerfile = fs.readFileSync(HERMES_DOCKERFILE, "utf-8"); - const adapterIntegrityGate = dockerfile.match( - /RUN printf '%s %s\\n' \\\n\s+"\$NEMOCLAW_HERMES_WRAPPER_SHA256"[^]*?\| sha256sum -c - \\\n\s+\|\| \{ echo "ERROR: Hermes CLI adapter integrity mismatch" >&2; exit 1; \}/u, - ); - const adapterValidation = dockerfile.indexOf( - "RUN /opt/hermes/.venv/bin/python -I \\\n /usr/local/lib/nemoclaw/validate-hermes-cli-adapter.py \\", - ); - - expect(adapterIntegrityGate).not.toBeNull(); - expect(adapterValidation).toBeGreaterThan(adapterIntegrityGate?.index ?? -1); - }); - it("rejects retired OpenClaw state represented as a directory", () => { const run = runFinalLayout({ openclaw: "directory" }); try { diff --git a/test/hosted-runner-recovery-workflow.test.ts b/test/hosted-runner-recovery-workflow.test.ts index df0ba8613f4..943ff86d64c 100644 --- a/test/hosted-runner-recovery-workflow.test.ts +++ b/test/hosted-runner-recovery-workflow.test.ts @@ -73,15 +73,6 @@ describe("hosted-runner recovery workflow boundary", () => { expect(Object.keys(value.jobs)).toEqual(["recover"]); }); - // source-shape-contract: security -- The exact source workflow name keeps the write-capable recovery subscription bound to the reviewed trusted-main identity - it("locks recovery to the platform workflow name (#7140)", () => { - const platform = sourceWorkflow(PLATFORM_WORKFLOW_PATH); - - expect(platform.name).toBe("CI / Platform Evidence"); - expect(platform).not.toHaveProperty("run-name"); - expect(workflow().on.workflow_run.workflows).toEqual([platform.name]); - }); - it("fails closed on controller, source, repository, branch, event, and path (#7140)", () => { const guard = workflow().jobs.recover.if ?? ""; for (const fragment of [ diff --git a/test/inference-options-docs.test.ts b/test/inference-options-docs.test.ts deleted file mode 100644 index b0611f53519..00000000000 --- a/test/inference-options-docs.test.ts +++ /dev/null @@ -1,536 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import fs from "node:fs"; -import { createRequire } from "node:module"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import type * as TypeScript from "typescript"; -import { describe, expect, it } from "vitest"; -import { parse } from "yaml"; -import { VLLM_IMAGES } from "../src/lib/inference/vllm.js"; -import { getSandboxRuntimeInferenceEndpoint } from "../src/lib/onboard/docker-gpu-local-inference.js"; -import { shouldForceCompletionsApi } from "../src/lib/validation.js"; - -const require = createRequire(import.meta.url); -const ts = require("typescript") as typeof TypeScript; -const { probeOpenAiLikeEndpoint } = require("../src/lib/inference/onboard-probes") as { - probeOpenAiLikeEndpoint: ( - endpointUrl: string, - model: string, - apiKey: string, - options?: { requireChatCompletionsToolCalling?: boolean }, - ) => { api: string | null; label: string | null; note?: string; ok: boolean }; -}; -const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); -const chooseModelPath = path.join(repoRoot, "docs", "inference", "choose-model.mdx"); -const hermesProviderPath = path.join(repoRoot, "docs", "inference", "use-hermes-provider.mdx"); -const releaseNotesPath = path.join(repoRoot, "docs", "changelog", "2026-07-09.mdx"); -const inferenceDocsDir = path.join(repoRoot, "docs", "inference"); -const docsNavPath = path.join(repoRoot, "docs", "index.yml"); -const fernDocsPath = path.join(repoRoot, "fern", "docs.yml"); -const compatibleEndpointPath = path.join( - repoRoot, - "docs", - "inference", - "set-up-openai-compatible-endpoint.mdx", -); -const inferenceRoutingPath = path.join( - repoRoot, - "docs", - "inference", - "how-inference-routing-works.mdx", -); -const compatibleApiPath = path.join( - repoRoot, - "docs", - "inference", - "choose-compatible-inference-api.mdx", -); -const localChoicePath = path.join( - repoRoot, - "docs", - "inference", - "choose-local-inference-server.mdx", -); -const vllmSetupPath = path.join(repoRoot, "docs", "inference", "set-up-vllm.mdx"); -const dualStationVllmPath = path.join( - repoRoot, - "docs", - "inference", - "set-up-vllm-on-two-dgx-stations.mdx", -); -const quickstartPath = path.join(repoRoot, "docs", "get-started", "quickstart.mdx"); -const troubleshootingPath = path.join(repoRoot, "docs", "reference", "troubleshooting.mdx"); -const verifyInferenceRoutePath = path.join( - repoRoot, - "docs", - "inference", - "verify-inference-route.mdx", -); -const subAgentSetupPath = path.join(repoRoot, "docs", "inference", "set-up-sub-agent.mdx"); -const inferenceConfigPath = path.join(repoRoot, "src", "lib", "inference", "config.ts"); -const modelPromptsPath = path.join(repoRoot, "src", "lib", "inference", "model-prompts.ts"); - -/** - * Removes TypeScript `as const` wrappers before inspecting literal AST nodes. - */ -function unwrapConstAssertion(expression: TypeScript.Expression): TypeScript.Expression { - return ts.isAsExpression(expression) ? unwrapConstAssertion(expression.expression) : expression; -} - -function readExportedConstInitializer( - sourcePath: string, - exportName: string, -): { sourceFile: TypeScript.SourceFile; initializer: TypeScript.Expression } { - const source = fs.readFileSync(sourcePath, "utf8"); - const sourceFile = ts.createSourceFile(sourcePath, source, ts.ScriptTarget.Latest, true); - - const declaration = sourceFile.statements - .filter( - (statement): statement is TypeScript.VariableStatement => - ts.isVariableStatement(statement) && - (statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) ?? - false), - ) - .flatMap((statement) => Array.from(statement.declarationList.declarations)) - .find((candidate) => candidate.name.getText(sourceFile) === exportName); - expect(declaration).toBeTruthy(); - - const initializer = declaration?.initializer && unwrapConstAssertion(declaration.initializer); - expect(initializer).toBeTruthy(); - - return { sourceFile, initializer: initializer as TypeScript.Expression }; -} - -function readCuratedCloudModelIds(): string[] { - const { sourceFile, initializer } = readExportedConstInitializer( - inferenceConfigPath, - "CLOUD_MODEL_OPTIONS", - ); - expect(ts.isArrayLiteralExpression(initializer)).toBe(true); - - return (initializer as TypeScript.ArrayLiteralExpression).elements.map((element) => { - expect(ts.isObjectLiteralExpression(element)).toBe(true); - const idProperty = (element as TypeScript.ObjectLiteralExpression).properties.find( - (property) => - ts.isPropertyAssignment(property) && - property.name.getText(sourceFile) === "id" && - ts.isStringLiteralLike(unwrapConstAssertion(property.initializer)), - ); - expect(idProperty).toBeTruthy(); - const idInitializer = unwrapConstAssertion( - (idProperty as TypeScript.PropertyAssignment).initializer, - ); - return (idInitializer as TypeScript.StringLiteral).text; - }); -} - -function readRemoteModelIds(providerKey: string): string[] { - const { sourceFile, initializer } = readExportedConstInitializer( - modelPromptsPath, - "REMOTE_MODEL_OPTIONS", - ); - expect(ts.isObjectLiteralExpression(initializer)).toBe(true); - - const providerProperty = (initializer as TypeScript.ObjectLiteralExpression).properties.find( - (property) => - ts.isPropertyAssignment(property) && property.name.getText(sourceFile) === providerKey, - ); - expect(providerProperty).toBeTruthy(); - - const providerInitializer = unwrapConstAssertion( - (providerProperty as TypeScript.PropertyAssignment).initializer, - ); - expect(ts.isArrayLiteralExpression(providerInitializer)).toBe(true); - - return (providerInitializer as TypeScript.ArrayLiteralExpression).elements.map((element) => { - expect(ts.isStringLiteralLike(unwrapConstAssertion(element))).toBe(true); - return (unwrapConstAssertion(element) as TypeScript.StringLiteral).text; - }); -} - -/** - * Reads curated onboarding model IDs from source config instead of duplicating them in docs tests. - */ -function readCuratedOnboardingModelIds(): string[] { - return [ - ...readCuratedCloudModelIds(), - ...readRemoteModelIds("openai"), - ...readRemoteModelIds("anthropic"), - ...readRemoteModelIds("gemini"), - ]; -} - -function stripFencedCodeBlocks(markdown: string): string { - return markdown.replace( - /^ {0,3}(`{3,})(?!`)[^\n]*\n[\s\S]*?^ {0,3}\1`*[ \t]*$|^ {0,3}(~{3,})(?!~)[^\n]*\n[\s\S]*?^ {0,3}\2~*[ \t]*$/gm, - "", - ); -} - -describe("inference options model task-fit docs (#4755)", () => { - // source-shape-contract: compatibility -- Published task-fit guidance must cover every curated onboarding model identifier - it("keeps a per-model task-fit comparison table for curated onboarding models", () => { - const markdown = fs.readFileSync(chooseModelPath, "utf8"); - const start = markdown.indexOf("## Model Task Fit"); - const end = markdown.indexOf("## Nemotron Deployment Choice", start); - expect(start).toBeGreaterThanOrEqual(0); - expect(end).toBeGreaterThan(start); - const section = markdown.slice(start, end); - - expect(section).toContain( - "| Model | Best for | Relative latency | Tool use | Context fit | Relative cost |", - ); - expect(markdown).toContain("Runtime route validation determines current availability"); - expect(section).not.toMatch(/\bTBD\b|\bTODO\b/i); - expect(section).not.toContain("Very large context"); - - const documentedModelIds = Array.from( - section.matchAll(/^\| `([^`]+)` \|/gm), - (match) => match[1], - ); - expect(documentedModelIds).toEqual(readCuratedOnboardingModelIds()); - }); - - it.each([ - ["GLM 5.1", /GLM-?5\.1|z-ai\/glm-5\.1/i, "`z-ai/glm-5.1`"], - ["Kimi K2.6", /Kimi K2\.6|moonshotai\/kimi-k2\.6/i, "`moonshotai/kimi-k2.6`"], - ])("keeps %s scoped to the independent Hermes Provider catalog", (_label, matcher, id) => { - const modelGuide = fs.readFileSync(chooseModelPath, "utf8"); - const hermesProvider = fs.readFileSync(hermesProviderPath, "utf8"); - - expect(modelGuide).not.toMatch(matcher as RegExp); - expect(hermesProvider).toContain(id); - }); -}); - -describe("inference setup navigation", () => { - it("strips indented fenced examples with longer closing markers", () => { - const prose = stripFencedCodeBlocks( - " ````md\n- fenced item\n\n- fenced item\n `````\n- prose item\n- prose item", - ); - - expect(prose).not.toContain("fenced item"); - expect(prose).toContain("- prose item"); - }); - - it("keeps simple list items compact across inference topics", () => { - const spacedListItems = - /^([ \t]*)(?:[-*+]|\d+\.)[ \t]+[^\n]+\n[ \t]*\n\1(?:[-*+]|\d+\.)[ \t]+/m; - - for (const fileName of fs - .readdirSync(inferenceDocsDir) - .filter((name) => name.endsWith(".mdx"))) { - const markdown = fs.readFileSync(path.join(inferenceDocsDir, fileName), "utf8"); - const prose = stripFencedCodeBlocks(markdown); - expect(prose, `${fileName} has a blank line between simple list items`).not.toMatch( - spacedListItems, - ); - } - }); - - it("routes the latest local and compatible inference release note through the shared chooser", () => { - const markdown = fs.readFileSync(releaseNotesPath, "utf8"); - const releaseStart = markdown.indexOf("## v0.0.79"); - expect(releaseStart).toBeGreaterThanOrEqual(0); - const release = markdown.slice(releaseStart); - const bulletStart = release.indexOf("- Local and compatible inference setup"); - const bulletEnd = release.indexOf("\n- ", bulletStart + 1); - expect(bulletStart).toBeGreaterThanOrEqual(0); - expect(bulletEnd).toBeGreaterThan(bulletStart); - const bullet = release.slice(bulletStart, bulletEnd); - - expect(bullet).toContain( - "[Choose a Local Inference Server](/user-guide/openclaw/inference/local-inference/choose-local-inference-server)", - ); - expect(bullet).not.toContain("/inference/local-inference/set-up-ollama"); - }); - - it("routes local options to focused setup pages", () => { - const markdown = fs.readFileSync(localChoicePath, "utf8"); - - expect(markdown).toContain("[Set Up Ollama](set-up-ollama)"); - expect(markdown).toContain("[Set Up vLLM](set-up-vllm)"); - expect(markdown).toContain("[Set Up NVIDIA NIM](set-up-nvidia-nim)"); - }); - - it("uses container-reachable binds with restricted exposure guidance (#5744)", () => { - const markdown = fs.readFileSync(compatibleEndpointPath, "utf8"); - const hostValues = Array.from( - markdown.matchAll(/--host(?:=|\s+)([^\s`\\]+)/g), - (match) => match[1], - ); - - expect(hostValues).toEqual(["0.0.0.0", "0.0.0.0"]); - expect(markdown).toContain("default-deny inbound rules"); - expect(markdown).toContain("only from the OpenShell Docker subnet to its gateway address"); - }); - - it("keeps broad flat local-inference redirects on the chooser", () => { - const config = parse(fs.readFileSync(fernDocsPath, "utf8")) as { - redirects: Array<{ source: string; destination: string }>; - }; - const redirects = new Map( - config.redirects.map(({ source, destination }) => [source, destination]), - ); - - expect(redirects.get("/nemoclaw/latest/inference/use-local-inference")).toBe( - "/nemoclaw/latest/user-guide/openclaw/inference/local-inference/choose-local-inference-server", - ); - expect(redirects.get("/nemoclaw/inference/use-local-inference")).toBe( - "/nemoclaw/user-guide/openclaw/inference/local-inference/choose-local-inference-server", - ); - }); - - it("uses a container-reachable bind with restricted exposure guidance", () => { - const markdown = fs.readFileSync(vllmSetupPath, "utf8"); - const hostValues = Array.from( - markdown.matchAll(/--host(?:=|\s+)([^\s`\\]+)/g), - (match) => match[1], - ); - - expect(hostValues).toEqual(["0.0.0.0"]); - expect(markdown).toContain("default-deny inbound rules"); - expect(markdown).toContain("only from the OpenShell Docker subnet to its gateway address"); - }); - - it("documents the dual-Station host-network trust boundary", () => { - const vllm = fs.readFileSync(vllmSetupPath, "utf8"); - const dualStation = fs.readFileSync(dualStationVllmPath, "utf8"); - - expect(vllm).toContain("Existing-server and single-host managed-vLLM paths need port `8000`"); - expect(vllm).toContain("[Set Up vLLM on Two DGX Stations](set-up-vllm-on-two-dgx-stations)"); - expect(vllm).not.toContain( - "qualified dual-Station runtime intentionally uses Docker host networking", - ); - expect(dualStation).toContain( - "qualified dual-Station runtime intentionally uses Docker host networking", - ); - expect(dualStation).toContain("Neither container publishes a Docker port"); - expect(dualStation).toContain("All Linux capabilities dropped"); - expect(dualStation).toContain("Only the selected GPU UUID and exact `uverbs` devices"); - expect(dualStation).toContain("worker does not receive the serving key"); - expect(dualStation).toContain("`/health` endpoint remains unauthenticated for readiness"); - expect(dualStation).toContain("Deny port `8000` on management and LAN interfaces"); - expect(dualStation).not.toContain( - "keeps its existing bridge-networked managed-inference topology instead of importing the playbook's host-network setting", - ); - expect(dualStation).not.toContain( - "NemoClaw needs port `8000` on host loopback for validation and on the OpenShell Docker bridge", - ); - }); - - it("keeps managed image tags, digests, and compressed sizes in sync with source", () => { - const markdown = fs.readFileSync(vllmSetupPath, "utf8"); - const entries = [ - { - prefix: "- DGX Spark and DGX Station models without a model-specific runtime", - image: VLLM_IMAGES.ngc2605Post1.arm64, - tag: VLLM_IMAGES.ngc2605Post1.tag, - }, - { - prefix: "- The DGX Station Nemotron 3 Ultra express recipe", - image: VLLM_IMAGES.vllm022.arm64, - tag: VLLM_IMAGES.vllm022.tag, - }, - { - prefix: "- Generic Linux `arm64` hosts", - image: VLLM_IMAGES.ngc2603Post1.arm64, - tag: VLLM_IMAGES.ngc2603Post1.tag, - }, - { - prefix: "- Generic Linux `amd64` hosts", - image: VLLM_IMAGES.ngc2603Post1.amd64, - tag: VLLM_IMAGES.ngc2603Post1.tag, - }, - ] as const; - - for (const { prefix, image, tag } of entries) { - const line = markdown.split("\n").find((candidate) => candidate.startsWith(prefix)); - expect(line, `missing managed-image documentation for ${prefix}`).toBeDefined(); - expect(line).toContain(`\`${image.ref.split("@")[1]}\``); - expect(line).toContain(`\`${(image.downloadSizeBytes / 1_000_000_000).toFixed(2)} GB\``); - expect(line).toContain(`\`${tag}\``); - } - }); - - it("documents the canonical Station Ultra recipe and DeepSeek demo override", () => { - const markdown = fs.readFileSync(vllmSetupPath, "utf8"); - - expect(markdown).toContain("--station-deepseek"); - expect(markdown).toContain("memory/stack ulimits"); - expect(markdown).toContain("MTP speculative decoding"); - expect(markdown).toContain("model-cache storage is insufficient"); - expect(markdown).toContain("not retained by the long-lived vLLM container"); - }); - - it("documents authenticated public-model downloads and resumable 429 recovery (#7157)", () => { - const vllm = fs.readFileSync(vllmSetupPath, "utf8"); - const quickstart = fs.readFileSync(quickstartPath, "utf8"); - - for (const markdown of [vllm, quickstart]) { - expect(markdown).toContain("https://huggingface.co/settings/tokens"); - expect(markdown).toContain("export HF_TOKEN="); - expect(markdown).toContain("HTTP `429`"); - expect(markdown).toContain("onboard --resume"); - expect(markdown).toContain("temporary model downloader"); - } - expect(vllm).toContain("public-model downloads continue anonymously"); - expect(vllm).toContain("Gated models still require license acceptance and a token"); - expect(quickstart).toContain("Before the Station express confirmation"); - }); - - it("keeps tool-calling remediation canonical in troubleshooting", () => { - const markdown = fs.readFileSync(troubleshootingPath, "utf8"); - const start = markdown.indexOf("### Tool calls appear as assistant text"); - expect(start).toBeGreaterThanOrEqual(0); - const nextHeading = markdown.indexOf("\n### ", start + 4); - const end = nextHeading === -1 ? markdown.length : nextHeading; - const section = markdown.slice(start, end); - - expect(section).toContain("[set up vLLM](../inference/local-inference/set-up-vllm)"); - expect( - fs.existsSync(path.join(repoRoot, "docs", "inference", "fix-tool-calling-failures.mdx")), - ).toBe(false); - - const nav = fs.readFileSync(docsNavPath, "utf8"); - expect(nav).toContain('section: "Validate Inference"'); - expect(nav).not.toContain('section: "Validate and Troubleshoot"'); - }); - - it("documents compatible-endpoint probing separately from runtime API selection", () => { - const markdown = fs.readFileSync(compatibleApiPath, "utf8"); - - expect(shouldForceCompletionsApi("openai-completions")).toBe(true); - expect(shouldForceCompletionsApi("openai-responses")).toBe(false); - expect(markdown).toContain("NemoClaw probes `/v1/responses` first"); - expect(markdown).toContain("the sandbox still uses `/v1/chat/completions`"); - expect(markdown).toContain( - "Set `NEMOCLAW_PREFERRED_API=openai-completions` to skip the Responses probe and validate only `/v1/chat/completions`.", - ); - }); - - it("scopes post-ready sandbox route verification to local inference providers", () => { - const markdown = fs.readFileSync(verifyInferenceRoutePath, "utf8"); - const start = markdown.indexOf("## Understand Local Provider Post-Ready Checks"); - const end = markdown.indexOf("## Understand Final Route Checks", start); - expect(start).toBeGreaterThanOrEqual(0); - expect(end).toBeGreaterThan(start); - const section = markdown.slice(start, end); - - expect(getSandboxRuntimeInferenceEndpoint("ollama-local")).toBe( - "https://inference.local/v1/models", - ); - expect(getSandboxRuntimeInferenceEndpoint("vllm-local")).toBe( - "https://inference.local/v1/models", - ); - expect(getSandboxRuntimeInferenceEndpoint("nvidia-nim")).toBeNull(); - expect(getSandboxRuntimeInferenceEndpoint("compatible-endpoint")).toBeNull(); - expect(section).toContain( - "For local Ollama, local vLLM, and local NVIDIA NIM on Docker GPU sandboxes using the compatibility route", - ); - expect(section).toContain("NVIDIA NIM and other compatible endpoints"); - }); - - it("documents universal final route verification separately from local warmup", () => { - const markdown = fs.readFileSync(verifyInferenceRoutePath, "utf8"); - const start = markdown.indexOf("## Understand Final Route Checks"); - const end = markdown.indexOf("## Send a Short Agent Request", start); - expect(start).toBeGreaterThanOrEqual(0); - expect(end).toBeGreaterThan(start); - const section = markdown.slice(start, end); - - expect(section).toContain("`https://inference.local/v1/models`"); - expect(section).toContain("retryable at final verification"); - expect(section).toContain("Provider setup still performs its own"); - }); - - it("explains the host-side validation limit of the containerized gateway alias", () => { - const markdown = fs.readFileSync(compatibleEndpointPath, "utf8"); - const result = probeOpenAiLikeEndpoint( - "http://host.openshell.internal:8000/v1", - "test-model", - "test-key", - ); - - expect(result).toMatchObject({ api: null, label: null, ok: true }); - expect(result.note).toContain("validation skipped"); - expect(markdown).toContain("`http://host.openshell.internal:8000/v1`"); - expect(markdown).toContain( - "To qualify for automatic rewriting, an HTTP endpoint URL must use the exact loopback host `localhost`, `127.0.0.1`, or `[::1]`.", - ); - expect(markdown).toContain( - "Automatic rewriting is limited to NemoClaw's bundled host-gateway ports: `8000`, `11434`, and `11435`.", - ); - expect(markdown).toContain( - "NemoClaw validates the entered URL from the host and registers the OpenShell gateway route through `host.openshell.internal:` for sandbox traffic.", - ); - expect(markdown).toContain( - "Sandbox inference requests continue to use the base `inference.local` policy, so the managed compatible-endpoint route does not require adding the `local-inference` preset.", - ); - expect(markdown).toContain( - "NemoClaw leaves URLs without an explicit port, URLs on `:80` or another privileged port, and URLs on unsupported ports unchanged.", - ); - expect(markdown).not.toContain("the default HTTP port or an unprivileged port"); - expect(markdown).toContain( - "if that bridge is unavailable, onboarding can still validate the host URL, but `$$nemoclaw status` is the authoritative runtime check.", - ); - expect(markdown).toContain( - "If you manually enter a sandbox-internal alias such as `http://host.openshell.internal:8000/v1`, host-side endpoint probing is skipped during onboarding.", - ); - expect(markdown).toContain( - "Use a host-routable endpoint such as `localhost` when you need onboarding to verify the API, tool-calling, and streaming paths", - ); - }); - - it("documents credential-free recovery of automatically bridged routes (#5744)", () => { - const markdown = fs.readFileSync(inferenceRoutingPath, "utf8"); - - expect(markdown).toContain( - "When a rebuild reuses an automatically bridged compatible-endpoint route without a host API key, NemoClaw reapplies the config-only bridge rewrite without reading or passing the credential stored in OpenShell.", - ); - }); - - it("keeps provider credentials out of documented helper argv", () => { - const markdown = fs.readFileSync(subAgentSetupPath, "utf8"); - - for (const secretName of [ - "NVIDIA_API_KEY", - "NGC_API_KEY", - "HF_TOKEN", - "HUGGING_FACE_HUB_TOKEN", - ]) { - const positionalSecret = new RegExp( - String.raw`\b(?:python3?|node|bash|sh)\b[^\n]*\$(?:\{)?${secretName}(?:\})?`, - ); - expect(markdown).not.toMatch(positionalSecret); - } - expect(markdown).toContain('os.environ["NVIDIA_API_KEY"]'); - }); - - it("keeps the Omni demo on the current hosted model identifier (#7729)", () => { - const markdown = fs.readFileSync(subAgentSetupPath, "utf8"); - - expect(markdown).toContain("`nvidia-omni/nvidia/nemotron-3-nano-omni-30b-a3b-reasoning`"); - expect(markdown).not.toContain( - "`nvidia-omni/private/nvidia/nemotron-3-nano-omni-reasoning-30b-a3b`", - ); - }); - - it("retains self-hosted setup and verification guidance across focused pages", () => { - const endpoint = fs.readFileSync(compatibleEndpointPath, "utf8"); - const vllm = fs.readFileSync(vllmSetupPath, "utf8"); - const verification = fs.readFileSync(verifyInferenceRoutePath, "utf8"); - - expect(endpoint).toContain("NEMOCLAW_MODEL=NVIDIA-Nemotron3-Nano-4B-Q4_K_M.gguf"); - expect(vllm).toContain( - "NemoClaw uses that value for the configured context window unless you set `NEMOCLAW_CONTEXT_WINDOW`.", - ); - expect(endpoint).toContain("Port `8000` is one of NemoClaw's bundled host-gateway ports."); - expect(vllm).toContain("Docker's `--restart unless-stopped` policy"); - expect(verification).toContain( - "The `Inference` row first checks the sandbox's `inference.local` path", - ); - }); -}); diff --git a/test/label-merged-pr-release-target-workflow.test.ts b/test/label-merged-pr-release-target-workflow.test.ts index 04061cecd72..0b06640c68c 100644 --- a/test/label-merged-pr-release-target-workflow.test.ts +++ b/test/label-merged-pr-release-target-workflow.test.ts @@ -180,52 +180,6 @@ async function runScript(harness: ReturnType): Promise { - // source-shape-contract: security -- Privileged label writes must stay metadata-only and serialize retirement with assignment - it("keeps fork-safe labeling inside the trusted metadata boundary", () => { - const coordination = { - group: "release-target-label-operations", - queue: "max", - }; - expect(workflow.on?.pull_request_target).toEqual({ - branches: ["main"], - types: ["closed"], - }); - expect(workflow.on).toHaveProperty("workflow_dispatch"); - expect(workflow.permissions).toEqual({ - contents: "read", - issues: "write", - "pull-requests": "write", - }); - expect(workflow.concurrency).toEqual(coordination); - expect(releaseWorkflow.concurrency).toEqual(coordination); - expect(releaseWorkflow.permissions).toEqual({ - contents: "write", - issues: "write", - "pull-requests": "write", - }); - expect(job.if).toBe( - "${{ github.event_name != 'pull_request_target' || github.event.pull_request.merged == true }}", - ); - expect(actionStep?.uses).toMatch(/^actions\/github-script@[0-9a-f]{40}$/u); - expect(job.steps).toHaveLength(1); - expect(job.steps?.some((step) => step.uses?.startsWith("actions/checkout@"))).toBe(false); - expect(job.steps?.some((step) => typeof step.run === "string")).toBe(false); - expect(script).not.toContain("containing release"); - expect(script).not.toContain("RECONCILIATION_WINDOW_MS"); - expect(retirementStep?.env).toMatchObject({ - GH_TOKEN: "${{ github.token }}", - }); - expect(retirementStep?.run).toContain("scripts/retire-release-label.mts"); - const latestIndex = releaseJob.steps?.findIndex( - (step) => step.name === "Move latest to the verified release tag object", - ); - const retirementIndex = releaseJob.steps?.findIndex( - (step) => step.name === "Retire the released target label", - ); - expect(latestIndex).toBeGreaterThanOrEqual(0); - expect(retirementIndex).toBeGreaterThan(latestIndex ?? -1); - }); - it.each([ ["pull request", undefined, "pull_request is missing"], [ diff --git a/test/mcp-openshell-workflow.test.ts b/test/mcp-openshell-workflow.test.ts index e0655d2a85c..00ae8cf610c 100644 --- a/test/mcp-openshell-workflow.test.ts +++ b/test/mcp-openshell-workflow.test.ts @@ -1,27 +1,11 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import fs from "node:fs"; - import { describe, expect, it } from "vitest"; -import credentialBoundaryManifest from "../src/lib/actions/sandbox/openshell-child-visible-credentials.v0.0.101.json"; import { validateMcpOpenShellWorkflowBoundary } from "../tools/e2e/mcp-workflow-boundary.mts"; describe("MCP OpenShell workflow boundary", () => { - // source-shape-contract: compatibility -- Setup guidance must advertise the pinned runtime compatibility boundary - it("keeps the setup docs aligned with the stable default", () => { - const setupDocs = fs.readFileSync("docs/deployment/set-up-mcp-bridge.mdx", "utf8"); - - expect(setupDocs).toContain( - `Current NemoClaw builds default to the pinned stable OpenShell \`${credentialBoundaryManifest.openshellVersion}\` release`, - ); - expect(setupDocs).toContain( - "The optional OpenShell development channel is compatibility evidence only and is not a shipping target.", - ); - expect(setupDocs).not.toContain("requires an OpenShell build from current main"); - }); - it("validates the unified stable and explicit-dev MCP workflow contract", () => { expect(validateMcpOpenShellWorkflowBoundary()).toEqual([]); }); diff --git a/test/mcp-tool-discovery-image-contract.test.ts b/test/mcp-tool-discovery-image-contract.test.ts index d280a6bfa23..a4432ee116f 100644 --- a/test/mcp-tool-discovery-image-contract.test.ts +++ b/test/mcp-tool-discovery-image-contract.test.ts @@ -103,108 +103,6 @@ function createCacheSeedFixture(): { } describe("MCP tool discovery image contract", () => { - // source-shape-contract: security -- Exact package pins and the CI audit mapping protect the shipped runtime graph - it("pins reviewed packages and audits their lock outside image builds (#8253)", () => { - const packageRoot = path.join(repoRoot, "tools", "mcp-tool-discovery-runtime"); - const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8")); - const lock = JSON.parse(fs.readFileSync(path.join(packageRoot, "package-lock.json"), "utf8")); - const auditConfig = JSON.parse( - fs.readFileSync(path.join(repoRoot, "ci", "reviewed-npm-audit.json"), "utf8"), - ); - const review = fs.readFileSync(path.join(packageRoot, "dependency-review.md"), "utf8"); - const installer = fs.readFileSync( - path.join(packageRoot, "install-reviewed-runtime.sh"), - "utf8", - ); - const reviewedSdk = { - name: "@modelcontextprotocol/sdk", - version: "1.30.0", - resolved: "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", - integrity: - "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", - } as const; - const reviewedPackages = { - "@hono/node-server": { - version: "2.0.12", - resolved: "https://registry.npmjs.org/@hono/node-server/-/node-server-2.0.12.tgz", - integrity: - "sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==", - }, - "fast-uri": { - version: "3.1.5", - resolved: "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", - integrity: - "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", - }, - hono: { - version: "4.12.34", - resolved: "https://registry.npmjs.org/hono/-/hono-4.12.34.tgz", - integrity: - "sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==", - }, - "ip-address": { - version: "10.3.1", - resolved: "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz", - integrity: - "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==", - }, - } as const; - - expect(manifest.dependencies[reviewedSdk.name]).toBe(reviewedSdk.version); - expect(lock.packages[`node_modules/${reviewedSdk.name}`]).toMatchObject({ - version: reviewedSdk.version, - resolved: reviewedSdk.resolved, - integrity: reviewedSdk.integrity, - }); - expect(review).toContain(`\`${reviewedSdk.name}@${reviewedSdk.version}\``); - expect(review).toContain(`\`${reviewedSdk.integrity}\``); - expect(manifest.overrides).toEqual( - Object.fromEntries( - Object.entries(reviewedPackages).map(([packageName, metadata]) => [ - packageName, - metadata.version, - ]), - ), - ); - for (const [packageName, metadata] of Object.entries(reviewedPackages)) { - expect(lock.packages[`node_modules/${packageName}`]).toMatchObject(metadata); - expect(review).toContain(`\`${packageName}@${metadata.version}\``); - expect(review).toContain(`\`${metadata.integrity}\``); - } - expect(installer).not.toContain("npm audit signatures"); - const reviewedAuditDriver = fs.readFileSync( - path.join(repoRoot, "scripts", "audit-reviewed-npm-graph.mts"), - "utf8", - ); - expect(reviewedAuditDriver).toContain('["audit", "signatures", "--omit=dev"]'); - expect(auditConfig.lockedGraphs).toContainEqual({ - id: "mcp-tool-discovery-runtime", - label: "MCP tool discovery runtime locked production graph", - packageSpec: `${reviewedSdk.name}@${reviewedSdk.version}`, - integrity: reviewedSdk.integrity, - tarballUrl: reviewedSdk.resolved, - directory: "tools/mcp-tool-discovery-runtime", - lockSha256: "bc7e34d9eb1f72cf3016c8b88c72d3b7682a4f234903cb93b9476b10d7e954eb", - }); - expect(installer).toContain( - 'export NODE_OPTIONS="${NODE_OPTIONS:---dns-result-order=ipv4first}"', - ); - expect(installer).toContain('export NPM_CONFIG_MAXSOCKETS="${NPM_CONFIG_MAXSOCKETS:-4}"'); - const openClawDockerfile = fs.readFileSync(path.join(repoRoot, "Dockerfile"), "utf8"); - expect(openClawDockerfile).toContain("FROM scratch AS mcp-tool-discovery-runtime"); - expect(openClawDockerfile).toContain( - "COPY tools/mcp-tool-discovery-runtime/npm-cache-seed/ /opt/nemoclaw-build-tools/npm-cache-seed/", - ); - expect(openClawDockerfile).toContain( - "COPY tools/mcp-tool-discovery-runtime/npm-cache-seed/ /usr/local/lib/nemoclaw-build-tools/npm-cache-seed/", - ); - expect(openClawDockerfile).toContain( - "COPY tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/mcp-tool-discovery/mcp-tool-discovery.bundle /opt/mcp-tool-discovery-runtime/dist/mcp-tool-discovery.mjs", - ); - expect(openClawDockerfile).not.toContain("mcp-runtime-npm-cache-seed/"); - expect(openClawDockerfile).not.toContain("install-reviewed-runtime.sh"); - }); - it.skipIf(process.platform === "win32")( "installs the complete pinned cache seed offline before registry access", async () => { @@ -375,59 +273,6 @@ describe("MCP tool discovery image contract", () => { }, ); - // source-shape-contract: compatibility -- Protected rebuilds must materialize mutable dependency graphs in explicit offline stages - it("pins dependency-materialization RUN cache identity", () => { - const openClawDockerfile = fs.readFileSync(path.join(repoRoot, "Dockerfile"), "utf8"); - const managedMessagingRuntimePackage = JSON.parse( - fs.readFileSync( - path.join(repoRoot, "agents/openclaw/managed-image-messaging-runtime/package.json"), - "utf8", - ), - ) as { dependencies: Record }; - const hermesDockerfile = fs.readFileSync( - path.join(repoRoot, "agents/hermes/Dockerfile"), - "utf8", - ); - const dcodeDockerfile = fs.readFileSync( - path.join(repoRoot, "agents/langchain-deepagents-code/Dockerfile"), - "utf8", - ); - - expect(openClawDockerfile.match(/--network=default\b/gu)).toHaveLength(3); - expect(openClawDockerfile.match(/^RUN --network=none\b/gmu)).toHaveLength(4); - expect(openClawDockerfile).toContain( - "RUN --network=none --mount=from=openclaw-optional-plugin-archives,target=/opt/nemoclaw-reviewed-npm-archives,ro", - ); - expect(openClawDockerfile).toContain("AS wechat-npm-cache"); - expect(openClawDockerfile).toContain("AS codex-acp-runtime"); - expect(managedMessagingRuntimePackage.dependencies).toEqual({ - "@openclaw/discord": "2026.7.1", - "@openclaw/googlechat": "2026.7.1", - "@openclaw/msteams": "2026.7.1", - "@openclaw/slack": "2026.7.1", - "@openclaw/whatsapp": "2026.7.1", - "@tencent-weixin/openclaw-weixin": "2.4.3", - "agent-base": "6.0.2", - axios: "1.18.0", - "https-proxy-agent": "5.0.1", - undici: "8.10.0", - }); - expect(openClawDockerfile).toContain("AS openclaw-managed-messaging-npm-cache-0"); - expect(openClawDockerfile).toContain("AS openclaw-managed-messaging-npm-cache-1"); - expect(openClawDockerfile).toContain( - "FROM openclaw-managed-messaging-npm-cache-${NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION} AS openclaw-managed-messaging-npm-cache", - ); - expect(openClawDockerfile).toContain( - "--archive-directory /opt/nemoclaw-build-tools/npm-cache-seed", - ); - expect(openClawDockerfile).toContain('--os linux --cpu "$npm_target_cpu" --libc glibc'); - expect(openClawDockerfile).toContain("--packuments-only"); - expect(openClawDockerfile).toContain('export NPM_CONFIG_CACHE="$install_cache"'); - expect(openClawDockerfile).toContain("export NPM_CONFIG_OFFLINE=true"); - expect(hermesDockerfile.match(/^RUN --network=default\b/gmu) ?? []).toHaveLength(0); - expect(dcodeDockerfile.match(/^RUN --network=default\b/gmu) ?? []).toHaveLength(0); - }); - it.each( dockerfiles, )("%s copies and probes the bundled runtime at its canonical path (#6901)", (relativePath) => { diff --git a/test/messaging-image-env-contract.test.ts b/test/messaging-image-env-contract.test.ts index fa58d12273f..c8be710d399 100644 --- a/test/messaging-image-env-contract.test.ts +++ b/test/messaging-image-env-contract.test.ts @@ -35,42 +35,4 @@ describe("messaging plan final image environment contract", () => { ).toEqual(["MODERN", "OTHER", "LEGACY", "LEGACY_B64"]); }); - // source-shape-contract: security -- Full serialized messaging plans must remain build-only while final agent images retain only reduced runtime metadata - it.each([ - ["OpenClaw", "Dockerfile.base", "Dockerfile", "openclaw"], - ["Hermes", "agents/hermes/Dockerfile.base", "agents/hermes/Dockerfile", "hermes"], - ])("%s keeps the full plan in build processes but not final runtime environments (#5896)", (_label, basePath, finalPath, agent) => { - const baseDockerfile = path.join(ROOT, basePath); - const finalDockerfile = path.join(ROOT, finalPath); - const dockerfile = fs.readFileSync(finalDockerfile, "utf-8"); - const planArgIndex = dockerfile.indexOf(`ARG ${MESSAGING_PLAN_ENV_KEY}=`); - - expect(planArgIndex).toBeGreaterThan(dockerfile.lastIndexOf("\nFROM ")); - const imageEnvNames = [baseDockerfile, finalDockerfile].flatMap((file) => - dockerfileEnvNames(fs.readFileSync(file, "utf-8")), - ); - expect(imageEnvNames).not.toContain(MESSAGING_PLAN_ENV_KEY); - - for (const phase of ["runtime-setup", "agent-install", "post-agent-install"]) { - const phaseIndex = dockerfile.indexOf(`--agent ${agent} --phase ${phase}`); - expect(phaseIndex, `${agent} is missing the ${phase} messaging build phase`).toBeGreaterThan( - planArgIndex, - ); - } - - const runtimeProbe = spawnSync( - process.execPath, - [ - "-e", - `process.stdout.write(String(Object.hasOwn(process.env, ${JSON.stringify(MESSAGING_PLAN_ENV_KEY)})))`, - ], - { - encoding: "utf-8", - env: Object.fromEntries(imageEnvNames.map((name) => [name, "image-config-value"])), - timeout: 5000, - }, - ); - expect(runtimeProbe.status, runtimeProbe.stderr).toBe(0); - expect(runtimeProbe.stdout).toBe("false"); - }); }); diff --git a/test/muse-glimmer-vllm-image-provenance.test.ts b/test/muse-glimmer-vllm-image-provenance.test.ts index cd8711afc0c..c789eb69e37 100644 --- a/test/muse-glimmer-vllm-image-provenance.test.ts +++ b/test/muse-glimmer-vllm-image-provenance.test.ts @@ -35,26 +35,6 @@ const recipe = YAML.parse(readFileSync(RECIPE_PATH, "utf8")) as { }; describe("Muse Glimmer vLLM image provenance", () => { - // source-shape-contract: security -- Exact manifest, publisher, platform, and source identities keep the credential-bearing managed runtime bound to the reviewed external image. - it("binds the selected runtime to its reviewed publisher, manifest, platform, and source", () => { - verifyMuseGlimmerVllmImageProvenance(provenance); - - expect(recipe.spec.runtime).toMatchObject({ - architecture: "arm64", - image: MUSE_GLIMMER_VLLM_IMAGE_REFERENCE, - imageDownloadSizeBytes: 9_699_710_136, - }); - - 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_699_710_136, - }); - }); - // 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"], diff --git a/test/onboard-performance-config-schema.test.ts b/test/onboard-performance-config-schema.test.ts index ef832a5f7b4..fae5e25e8ed 100644 --- a/test/onboard-performance-config-schema.test.ts +++ b/test/onboard-performance-config-schema.test.ts @@ -396,334 +396,3 @@ function validationProvenanceViolations( ), }; } - -describe("full-E2E cold-path calibration", () => { - // source-shape-contract: compatibility -- SHA provenance is durable evidence for the hosted-run budget calibration - it("records five independent successful samples for current main", () => { - expect(calibration.schemaVersion).toBe(1); - expect(calibration.baselineMainSha).toMatch(/^[0-9a-f]{40}$/u); - expect(calibration.measurementHeadSha).toMatch(/^[0-9a-f]{40}$/u); - expect(calibration.derivation.percentileMethod).toBe("nearest-rank"); - expect(calibration.samples).toHaveLength(5); - expect(new Set(calibration.samples.map((sample) => sample.runId)).size).toBe(5); - - for (const sample of calibration.samples) { - expect(sample.runUrl).toBe(`https://github.com/NVIDIA/NemoClaw/actions/runs/${sample.runId}`); - expect(sample.headSha).toBe(calibration.measurementHeadSha); - expect(sample).toMatchObject({ - conclusion: "success", - installExitCode: 0, - firstTurnExitCode: 0, - performancePassed: true, - usedBuildKitPrebuild: true, - buildKitFallback: false, - }); - expect(sample.maxSilenceSecs).toBeLessThanOrEqual(60); - expect(sample.responseChars).toBeGreaterThan(0); - expect(Object.keys(sample.measurementsMs.phases).sort()).toEqual([...PHASE_NAMES].sort()); - for (const value of [ - sample.measurementsMs.onboardRoot, - sample.measurementsMs.rootStartToFirstTurnCompletion, - sample.measurementsMs.rootEndToInstallCompletion, - sample.measurementsMs.firstTurnCommand, - sample.measurementsMs.rootEndToFirstTurnCompletion, - ...Object.values(sample.measurementsMs.phases), - ]) { - expect(Number.isFinite(value) && value >= 0).toBe(true); - } - } - }); - - // source-shape-contract: compatibility -- Recomputed thresholds keep enforced budgets tied to the reviewed calibration evidence - it("keeps baseline budgets derived from the checked-in samples", () => { - const derived = deriveBudgets(calibration); - expect(calibration.derivedBudgetsMs).toEqual(derived); - }); - - // source-shape-contract: compatibility -- Post-image-growth validation may adjust only observed stale cold-path caps without pretending to replace the five-run calibration - it("keeps interim cap adjustments tied to functional post-change evidence", () => { - const validation = calibration.validationAdjustment!; - expect(validation.validatedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/u); - expect(validation.imageChangeSha).toMatch(/^[0-9a-f]{40}$/u); - expect(validation.imageInputsVerifiedThroughSha).toMatch(/^[0-9a-f]{40}$/u); - expect(validation.imageInputPaths.length).toBeGreaterThan(0); - expect(validation.imageInputPaths).toEqual( - expect.arrayContaining([ - "scripts/patch-openclaw-tool-catalog.mts", - "scripts/patch-openclaw-chat-send.mts", - "scripts/patch-openclaw-mcp-npx.mts", - "scripts/patch-openclaw-mcp-reliability.mts", - "scripts/patch-openclaw-issue-4434-diagnostics.mts", - "scripts/patch-openclaw-device-self-approval.mts", - ]), - ); - expect(validation.imageInputPaths).not.toEqual( - expect.arrayContaining([ - "scripts/patch-openclaw-tool-catalog.js", - "scripts/patch-openclaw-chat-send.js", - "scripts/patch-openclaw-issue-4434-diagnostics.ts", - "scripts/patch-openclaw-device-self-approval.ts", - ]), - ); - expect(validationProvenanceViolations(validation)).toEqual({ - nonDescendantRunHeads: [], - runHeadsBeyondVerifiedInputs: [], - runHeadsWithChangedImageInputs: [], - changedImageInputsThroughBoundary: [], - }); - expect( - validationProvenanceViolations({ - ...validation, - runs: [{ ...validation.runs[0], headSha: calibration.baselineMainSha }], - }).nonDescendantRunHeads, - ).toEqual([calibration.baselineMainSha]); - const currentHeadSha = gitRevision("HEAD"); - expect( - validationProvenanceViolations({ - ...validation, - runs: [{ ...validation.runs[0], headSha: currentHeadSha }], - }).runHeadsBeyondVerifiedInputs, - ).toEqual([currentHeadSha]); - const staleImageReference = validationProvenanceViolations({ - ...validation, - imageChangeSha: calibration.baselineMainSha, - }); - expect(staleImageReference.runHeadsWithChangedImageInputs.map((run) => run.headSha)).toEqual( - validation.runs.map((run) => run.headSha), - ); - expect( - staleImageReference.runHeadsWithChangedImageInputs.flatMap((run) => run.changedPaths), - ).toContain("agents/openclaw/wechat-runtime/package.json"); - expect(staleImageReference.changedImageInputsThroughBoundary).toContain( - "agents/openclaw/wechat-runtime/package.json", - ); - expect(validation.adjustedMetrics).toEqual([ - "rootStartToFirstTurnCompletion", - "nemoclaw.onboard.phase.sandbox", - ]); - expect(validation.derivation.statistic).toBe("maximum"); - expect(validation.retirement).toEqual({ - trigger: "successful-single-sha-calibration", - minimumSampleCount: 5, - allSamplesSameHead: true, - imageChangeMustBeAncestor: true, - action: "replace-baseline-and-remove-adjustment", - }); - expect(validation.runs).toHaveLength(4); - expect(new Set(validation.runs.map((run) => run.runId)).size).toBe(4); - expect(validation.runs.map((run) => run.conclusion).sort()).toEqual([ - "failure", - "failure", - "success", - "success", - ]); - expect(validation.runs.map((run) => run.performancePassed).sort()).toEqual([ - false, - false, - true, - true, - ]); - - for (const run of validation.runs) { - expect(run.runUrl).toBe(`https://github.com/NVIDIA/NemoClaw/actions/runs/${run.runId}`); - expect(run.headSha).toMatch(/^[0-9a-f]{40}$/u); - expect(run).toMatchObject({ - installExitCode: 0, - firstTurnExitCode: 0, - usedBuildKitPrebuild: true, - buildKitFallback: false, - }); - expect(run.maxSilenceSecs).toBeLessThanOrEqual(60); - expect(run.responseChars).toBeGreaterThan(0); - } - - expect(validation.derivedCapsMs).toEqual({ - rootStartToFirstTurnCompletionBudgetMs: validationThreshold( - validation.runs.map((run) => run.measurementsMs.rootStartToFirstTurnCompletion), - validation.derivation, - ), - sandboxPhaseBudgetMs: validationThreshold( - validation.runs.map((run) => run.measurementsMs.phases["nemoclaw.onboard.phase.sandbox"]), - validation.derivation, - ), - }); - expect(checkedInConfig.fullE2eColdPath).toEqual(effectiveBudgets(calibration)); - expect( - effectiveBudgets({ - ...calibration, - validationAdjustment: undefined, - restartSafeStartupAdjustment: undefined, - }), - ).toEqual({ - authoritativeLocalBaseBuildAllowanceMs: - calibration.authoritativeLocalBaseBuildAdjustment.derivedAllowanceMs, - ...calibration.derivedBudgetsMs, - }); - - const startupAdjustment = calibration.restartSafeStartupAdjustment!; - expect(startupAdjustment.validatedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/u); - expect(startupAdjustment.changeSha).toMatch(/^[0-9a-f]{40}$/u); - expect(startupAdjustment.runtimeInputsVerifiedThroughSha).toMatch(/^[0-9a-f]{40}$/u); - expect(startupAdjustment.triggerOutput).toBe( - "Recreating OpenShell Docker sandbox container with restart-safe startup...", - ); - expect(startupAdjustment.adjustedMetrics).toEqual([ - "rootStartToFirstTurnCompletion", - "nemoclaw.onboard.phase.sandbox", - ]); - expect(startupAdjustment.derivation.statistic).toBe("maximum"); - expect(startupAdjustment.runs).toHaveLength(5); - expect(new Set(startupAdjustment.runs.map((run) => run.runId)).size).toBe(5); - expect(new Set(startupAdjustment.runs.map((run) => run.jobId)).size).toBe(5); - expect(new Set(startupAdjustment.runs.map((run) => run.testedSha)).size).toBe(5); - expect( - Object.fromEntries(startupAdjustment.runs.map((run) => [run.runId, run.testedSha])), - ).toEqual({ - 30614075121: "387cb08644fe030bb85146255f4b77e3c54697d2", - 30615995748: "915b25c522d982fc7d40d01e583bc8f15bcf975f", - 30619965759: "c3106eea0669aa645c0ff6f51adce0badf24477f", - 30620296004: "f8fb820159c4843a19759efc9b0e28d4aa122440", - 30620879680: "d1b24c97c348215574fd8c55435a2e8c5e0d86e1", - }); - expect( - changedInputs( - startupAdjustment.changeSha, - startupAdjustment.runtimeInputsVerifiedThroughSha, - startupAdjustment.runtimeInputPaths, - ), - ).toEqual([]); - - for (const run of startupAdjustment.runs) { - expect(run.runUrl).toBe(`https://github.com/NVIDIA/NemoClaw/actions/runs/${run.runId}`); - expect(run.workflowHeadSha).toMatch(/^[0-9a-f]{40}$/u); - expect(run.testedSha).toMatch(/^[0-9a-f]{40}$/u); - expect(gitIsAncestor(startupAdjustment.changeSha, run.workflowHeadSha)).toBe(true); - // A tested revision can be a PR merge or head commit that GitHub stops - // advertising after the PR closes. The run and job receipts bind that - // exact SHA; local ancestry uses the durable workflow head instead. - expect( - gitIsAncestor(run.workflowHeadSha, startupAdjustment.runtimeInputsVerifiedThroughSha), - ).toBe(true); - expect(run).toMatchObject({ - installExitCode: 0, - firstTurnExitCode: 0, - firstTurnSentinelMatched: true, - usedBuildKitPrebuild: true, - buildKitFallback: false, - responseChars: 23, - triggerEvidence: { - artifact: "e2e-full-e2e", - path: "full-e2e-install-onboard-inference-cli-operations-and-cleanup/shell/phase-1-install-sh.stdout.txt", - output: startupAdjustment.triggerOutput, - }, - }); - expect(run.maxSilenceSecs).toBeLessThanOrEqual(60); - } - expect(startupAdjustment.runs.map((run) => run.conclusion).sort()).toEqual([ - "failure", - "failure", - "failure", - "failure", - "success", - ]); - expect(startupAdjustment.runs.map((run) => run.performancePassed).sort()).toEqual([ - false, - false, - false, - false, - true, - ]); - expect(startupAdjustment.retirement).toEqual({ - trigger: "successful-single-sha-calibration", - minimumSampleCount: 5, - allSamplesSameHead: true, - runtimeChangeMustBeAncestor: true, - action: "replace-baseline-and-remove-adjustment", - }); - expect(startupAdjustment.derivedCapsMs).toEqual({ - rootStartToFirstTurnCompletionBudgetMs: validationThreshold( - startupAdjustment.runs.map((run) => run.rootStartToFirstTurnCompletionMs), - startupAdjustment.derivation, - ), - sandboxPhaseBudgetMs: validationThreshold( - startupAdjustment.runs.map((run) => run.sandboxPhaseMs), - startupAdjustment.derivation, - ), - }); - expect(checkedInConfig.fullE2eColdPath).toEqual(effectiveBudgets(calibration)); - }); - - // source-shape-contract: compatibility -- Exact PR run evidence keeps the local-build allowance bounded and reproducible - it("keeps the authoritative local-build allowance tied to exact PR evidence", () => { - const adjustment = calibration.authoritativeLocalBaseBuildAdjustment; - expect(adjustment.validatedAt).toMatch(/^\d{4}-\d{2}-\d{2}$/u); - expect(adjustment.triggerOutput).toContain("Building OpenClaw sandbox base image locally"); - expect(adjustment.adjustedMetrics).toEqual([ - "rootStartToFirstTurnCompletion", - "nemoclaw.onboard.phase.sandbox", - ]); - expect(adjustment.derivation.statistic).toBe("maximum-budget-excess"); - expect(adjustment.runs.length).toBeGreaterThanOrEqual(2); - expect(new Set(adjustment.runs.map((run) => run.runId)).size).toBe(adjustment.runs.length); - for (const run of adjustment.runs) { - expect(run.runUrl).toBe(`https://github.com/NVIDIA/NemoClaw/actions/runs/${run.runId}`); - expect(run.headSha).toMatch(/^[0-9a-f]{40}$/u); - expect(run.triggerEvidence).toEqual({ - artifact: "e2e-full-e2e", - path: "full-e2e-install-onboard-inference-cli-operations-and-cleanup/shell/phase-1-install-sh.stderr.txt", - output: adjustment.triggerOutput, - }); - expect(new Set(run.nativeSecurityInputPaths).size).toBe(run.nativeSecurityInputPaths.length); - } - expect( - adjustment.runs.map((run) => ({ - headSha: run.headSha, - nativeSecurityInputPaths: run.nativeSecurityInputPaths, - })), - ).toEqual([ - { - headSha: "188d9a75b3e5efdafeb38e885138bb196197574f", - nativeSecurityInputPaths: [], - }, - { - headSha: "188d9a75b3e5efdafeb38e885138bb196197574f", - nativeSecurityInputPaths: [], - }, - { - headSha: "5f190e4948a11f8b05655e085c11803ce0a9a0a8", - nativeSecurityInputPaths: [ - "Dockerfile.base", - "scripts/security/build-native-security-packages.sh", - "scripts/security/patches/libssh2-1.11.1-cve-2026.patch", - "scripts/security/patches/python3.13-htmlparser-cve-2026-15308.patch", - ], - }, - ]); - expect(adjustment.retirement).toEqual({ - trigger: "successful-single-sha-calibration", - minimumSampleCount: 5, - allSamplesSameHead: true, - nativeSecurityInputsMustBeUnchanged: true, - action: "replace-baseline-and-remove-adjustment", - }); - const maximumExcessMs = Math.max( - ...adjustment.runs.flatMap((run) => [ - run.rootStartToFirstTurnCompletionMs - - checkedInConfig.fullE2eColdPath.rootStartToFirstTurnCompletionBudgetMs, - run.sandboxPhaseMs - - checkedInConfig.fullE2eColdPath.phaseBudgetsMs["nemoclaw.onboard.phase.sandbox"], - ]), - ); - const headroomMs = Math.max( - adjustment.derivation.minimumHeadroomMs, - maximumExcessMs * (adjustment.derivation.relativeHeadroomPercent / 100), - ); - expect(adjustment.derivedAllowanceMs).toBe( - Math.ceil((maximumExcessMs + headroomMs) / adjustment.derivation.roundUpMs) * - adjustment.derivation.roundUpMs, - ); - expect(checkedInConfig.fullE2eColdPath.authoritativeLocalBaseBuildAllowanceMs).toBe( - adjustment.derivedAllowanceMs, - ); - }); -}); diff --git a/test/openclaw-dependency-review.test.ts b/test/openclaw-dependency-review.test.ts index b252504ebea..b561a24b365 100644 --- a/test/openclaw-dependency-review.test.ts +++ b/test/openclaw-dependency-review.test.ts @@ -553,25 +553,6 @@ describe("OpenClaw 2026.6.10 dependency review contract", () => { expect(review).toContain("test/onboard-resume-provider-recovery.test.ts"); }); - // source-shape-contract: security -- The legacy archive remediation helper must be present in the base image before the fail-closed Docker build invokes it - it("copies the legacy OpenClaw remediation helper before the base build invokes it", () => { - const dockerfile = readFileSync(path.join(REPO_ROOT, "Dockerfile.base"), "utf-8"); - const flattenedDockerfile = dockerfile.replace(/\\\s*\n/g, " ").replace(/\s+/g, " "); - const groupedHelperCopy = flattenedDockerfile.indexOf( - "COPY scripts/lib/reviewed-npm-archive.mts scripts/lib/reviewed-npm-audit.mts scripts/lib/openclaw-npm-remediation.mts /scripts/lib/", - ); - const legacyHelperCopy = flattenedDockerfile.indexOf( - "COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts", - ); - const helperCopy = groupedHelperCopy >= 0 ? groupedHelperCopy : legacyHelperCopy; - const helperInvocation = flattenedDockerfile.indexOf( - "node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts", - ); - - expect(helperCopy).toBeGreaterThanOrEqual(0); - expect(helperInvocation).toBeGreaterThan(helperCopy); - }); - it("keeps every reviewed archive boundary on the shared invariant matrix (#5896)", () => { const result = spawnSync( "bash", diff --git a/test/openclaw-final-image-layout.test.ts b/test/openclaw-final-image-layout.test.ts index 91a4e2141a5..eeda2aa2dab 100644 --- a/test/openclaw-final-image-layout.test.ts +++ b/test/openclaw-final-image-layout.test.ts @@ -34,227 +34,4 @@ describe("OpenClaw final image layout", () => { expect(hasBuildKitRunMount(dockerfile)).toBe(expected); }); - // source-shape-contract: compatibility -- Legacy-compatible grouped payload copies preserve cold-onboard export work while retaining intentional cache and scan boundaries - it("uses grouped legacy-compatible payload layers at their cache boundaries (#7611)", () => { - const dockerfile = fs.readFileSync(DOCKERFILE, "utf-8"); - const stages = dockerfile.split(/(?=^FROM )/mu).filter((stage) => stage.startsWith("FROM ")); - const finalStageIndex = stages.findIndex((stage) => stage.startsWith("FROM ${BASE_IMAGE}")); - const finalStage = stages[finalStageIndex] ?? ""; - const entrypoint = fs.readFileSync(path.join(ROOT, "scripts", "nemoclaw-start.sh"), "utf-8"); - const payloads = [ - { - stage: "openclaw-dependency-payload", - copies: [ - "COPY agents/openclaw/openclaw-runtime/package.json /usr/local/lib/nemoclaw/openclaw-runtime/package.json", - "COPY agents/openclaw/openclaw-runtime/package-lock.json /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json", - "COPY agents/openclaw/mcporter-runtime/package.json /usr/local/lib/nemoclaw/mcporter-runtime/package.json", - "COPY agents/openclaw/mcporter-runtime/package-lock.json /usr/local/lib/nemoclaw/mcporter-runtime/package-lock.json", - "COPY agents/openclaw/wechat-runtime/package.json /usr/local/lib/nemoclaw/wechat-runtime/package.json", - "COPY agents/openclaw/wechat-runtime/package-lock.json /usr/local/lib/nemoclaw/wechat-runtime/package-lock.json", - "COPY ci/npm-audit-exceptions.json /scripts/npm-audit-exceptions.json", - "COPY scripts/lib/reviewed-npm-archive.mts /scripts/lib/reviewed-npm-archive.mts", - "COPY scripts/lib/reviewed-npm-audit.mts /scripts/lib/reviewed-npm-audit.mts", - "COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts", - "COPY scripts/patch-bundled-npm-brace-expansion.mts /scripts/patch-bundled-npm-brace-expansion.mts", - "COPY scripts/lib/patch-bundled-npm-ip-address.mts /scripts/lib/patch-bundled-npm-ip-address.mts", - "COPY scripts/patch-bundled-npm-tar.mts /scripts/patch-bundled-npm-tar.mts", - ], - }, - { - stage: "openclaw-plugin-payload", - copies: [ - "COPY --from=builder /opt/nemoclaw/dist/ /opt/nemoclaw/dist/", - "COPY nemoclaw/openclaw.plugin.json /opt/nemoclaw/", - "COPY nemoclaw-blueprint/ /opt/nemoclaw-blueprint/", - ], - }, - { - stage: "openclaw-patch-payload", - copies: [ - "COPY scripts/patch-openclaw-tool-catalog.mts /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts", - "COPY scripts/patch-openclaw-chat-send.mts /usr/local/lib/nemoclaw/patch-openclaw-chat-send.mts", - "COPY scripts/patch-openclaw-mcp-npx.mts /usr/local/lib/nemoclaw/patch-openclaw-mcp-npx.mts", - "COPY scripts/patch-openclaw-mcp-reliability.mts /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts", - "COPY scripts/patch-openclaw-mcp-tools-list-timeout.mts /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts", - "COPY scripts/patch-openclaw-issue-4434-diagnostics.mts /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts", - "COPY scripts/patch-openclaw-managed-transport-diagnostics.mts /usr/local/lib/nemoclaw/patch-openclaw-managed-transport-diagnostics.mts", - "COPY scripts/patch-openclaw-device-self-approval.mts /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts", - "COPY scripts/openclaw/patch-gateway-daemon-dialback.mts /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts", - "COPY scripts/extract-semver.sh /usr/local/lib/nemoclaw/extract-semver", - "COPY scripts/patch-openclaw-shared-state-permissions.mts /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts", - "COPY scripts/verify-wechat-runtime-lock.mts /usr/local/lib/nemoclaw/verify-wechat-runtime-lock.mts", - ], - }, - { - stage: "openclaw-runtime-payload", - copies: [ - "COPY scripts/lib/sandbox-init.sh /usr/local/lib/nemoclaw/sandbox-init.sh", - "COPY scripts/lib/entrypoint-env-wrapper.sh /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh", - "COPY scripts/lib/gateway-supervisor.sh /usr/local/lib/nemoclaw/gateway-supervisor.sh", - "COPY scripts/lib/sandbox-rlimits.sh /usr/local/lib/nemoclaw/sandbox-rlimits.sh", - "COPY scripts/lib/openclaw_device_approval_policy.py /usr/local/lib/nemoclaw/openclaw_device_approval_policy.py", - "COPY scripts/lib/clean_runtime_shell_env_shim.py /usr/local/lib/nemoclaw/clean_runtime_shell_env_shim.py", - "COPY scripts/lib/normalize_mutable_config_perms.py /usr/local/lib/nemoclaw/normalize_mutable_config_perms.py", - "COPY scripts/state-dir-guard.py /usr/local/lib/nemoclaw/state-dir-guard.py", - "COPY agents/openclaw/state-lock-plan.json /usr/local/share/nemoclaw/state-lock-plan.json", - "COPY scripts/openclaw-config-guard.py /usr/local/lib/nemoclaw/openclaw-config-guard.py", - "COPY scripts/managed-gateway-control.py /usr/local/lib/nemoclaw/managed-gateway-control.py", - "COPY scripts/nemoclaw-start.sh /usr/local/bin/nemoclaw-start", - "COPY scripts/managed-startup-hold.sh /usr/local/bin/nemoclaw-managed-startup-hold", - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/bin/nemoclaw-managed-bootstrap /usr/local/bin/nemoclaw-managed-bootstrap", - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh /usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh", - "COPY scripts/gateway-control.sh /usr/local/bin/nemoclaw-gateway-control", - "COPY nemoclaw-blueprint/scripts/*.js /usr/local/lib/nemoclaw/preloads/", - "COPY --from=runtime-preload-builder /opt/nemoclaw-root/dist/lib/messaging/channels/ /usr/local/lib/nemoclaw/preloads-compiled-channels/", - "COPY scripts/codex-acp-wrapper.sh /usr/local/bin/nemoclaw-codex-acp", - "COPY scripts/generate-openclaw-config.mts /scripts/generate-openclaw-config.mts", - "COPY scripts/validate-openclaw-tool-search.mts /scripts/validate-openclaw-tool-search.mts", - "COPY --from=managed-startup-runtime-builder /out/managed-startup-image-runtime.cjs /usr/local/lib/nemoclaw/managed-startup-image-runtime.cjs", - "COPY src/lib/tool-disclosure.ts /src/lib/tool-disclosure.ts", - "COPY src/lib/messaging/ /src/lib/messaging/", - "COPY nemoclaw-blueprint/openclaw-plugins/ /usr/local/share/nemoclaw/openclaw-plugins/", - "COPY --from=mcp-tool-discovery-runtime /opt/mcp-tool-discovery-runtime/dist/ /usr/local/lib/nemoclaw/mcp-tool-discovery-runtime/", - ], - }, - ] as const; - const dependencyCopy = "COPY --from=openclaw-dependency-payload / /"; - const pluginCopy = "COPY --from=openclaw-plugin-payload / /"; - const patchCopy = "COPY --from=openclaw-patch-payload / /"; - const runtimeCopy = "COPY --from=openclaw-runtime-payload / /"; - - expect(finalStageIndex).toBe(stages.length - 1); - expect(hasBuildKitRunMount(finalStage)).toBe(true); - expect(finalStage.match(/^RUN[^\n]*--mount[^\n]*/gmu)).toEqual([ - "RUN --network=none --mount=from=openclaw-optional-plugin-archives,target=/opt/nemoclaw-reviewed-npm-archives,ro set -eu; \\", - "RUN --mount=from=openclaw-managed-messaging-npm-cache,source=/out/npm-cache,target=/opt/nemoclaw-managed-messaging-npm-cache,ro set -eu; \\", - ]); - expectManagedBootstrapNativeImageContract(dockerfile); - expect(finalStage).not.toMatch(/^\s*ENV\b[^\n]*(?:\\\n[^\n]*)*NODE_OPTIONS=/mu); - expect(finalStage).toContain( - "RUN --network=default if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \\", - ); - expect(finalStage).toContain( - " NODE_OPTIONS=--dns-result-order=ipv4first \\\n /usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh --omit=dev", - ); - expect(entrypoint).toContain('export NODE_OPTIONS="--dns-result-order=ipv4first"'); - expect( - indexOfRequired(entrypoint, 'export NODE_OPTIONS="--dns-result-order=ipv4first"'), - ).toBeLessThan(indexOfRequired(entrypoint, "# managed-entrypoint-env-wrapper begin")); - for (const payload of payloads) { - const stage = stages.find((entry) => entry.startsWith(`FROM scratch AS ${payload.stage}`)); - expect(stage?.match(/^COPY\b.*$/gmu)).toEqual(payload.copies); - expect(finalStage).toContain(`COPY --from=${payload.stage} / /`); - } - expect(finalStage.match(/^COPY\b.*$/gmu)).toEqual([ - "COPY --from=builder /usr/local/bin/node /usr/local/bin/node", - dependencyCopy, - "COPY nemoclaw/package.json nemoclaw/package-lock.json /opt/nemoclaw/", - "COPY tools/mcp-tool-discovery-runtime/npm-ci-locked.sh /usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh", - "COPY tools/mcp-tool-discovery-runtime/npm-cache-seed/ /usr/local/lib/nemoclaw-build-tools/npm-cache-seed/", - pluginCopy, - "COPY --from=wechat-npm-cache /out/wechat-npm-cache/ /usr/local/share/nemoclaw/wechat-npm-cache/", - patchCopy, - "COPY --from=codex-acp-runtime /usr/local/lib/node_modules/@zed-industries/ /usr/local/lib/node_modules/@zed-industries/", - "COPY --from=codex-acp-runtime /usr/local/bin/codex-acp /usr/local/bin/codex-acp", - runtimeCopy, - ]); - for (const metadataContract of [ - "/scripts/patch-bundled-npm-brace-expansion.mts 'root:root:755'", - "/scripts/lib/patch-bundled-npm-ip-address.mts 'root:root:755'", - "/scripts/patch-bundled-npm-tar.mts 'root:root:755'", - "/opt/nemoclaw/openclaw.plugin.json 'root:root:644'", - "/usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts 'root:root:755'", - "/usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts 'root:root:755'", - "/usr/local/bin/nemoclaw-managed-bootstrap 'root:root:755'", - "/usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh 'root:root:444'", - "/usr/local/bin/nemoclaw-gateway-control 'root:root:700'", - "/usr/local/lib/nemoclaw/state-dir-guard.py 'root:root:500'", - "/usr/local/share/nemoclaw/state-lock-plan.json 'root:root:444'", - "/usr/local/lib/nemoclaw/preloads/sandbox-safety-net.js 'root:root:644'", - ]) { - expect(finalStage).toContain(`check_metadata ${metadataContract}`); - } - - const dependency = indexOfRequired(finalStage, dependencyCopy); - const plugin = indexOfRequired(finalStage, pluginCopy); - const patch = indexOfRequired(finalStage, patchCopy); - const runtime = indexOfRequired(finalStage, runtimeCopy); - const tarPatch = indexOfRequired( - finalStage, - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", - ); - const braceExpansionPatch = indexOfRequired( - finalStage, - "node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts", - ); - const ipAddressPatch = indexOfRequired( - finalStage, - "node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts", - ); - const dependencyInstall = indexOfRequired( - finalStage, - "NODE_OPTIONS=--dns-result-order=ipv4first \\\n /usr/local/lib/nemoclaw-build-tools/npm-ci-locked.sh --omit=dev", - ); - const managedMessagingUnionInstall = indexOfRequired( - finalStage, - "--agent openclaw --phase managed-image-capability-union", - ); - const messagingPostInstall = indexOfRequired( - finalStage, - "--agent openclaw --phase post-agent-install", - ); - const neutralConfigRegeneration = indexOfRequired( - finalStage, - "# A managed image is a neutral capability carrier", - ); - const pluginChmod = indexOfRequired( - finalStage, - "RUN chmod -R a+rX /opt/nemoclaw /opt/nemoclaw-blueprint/", - ); - const wechatInstall = indexOfRequired( - finalStage, - "COPY --from=wechat-npm-cache /out/wechat-npm-cache/ /usr/local/share/nemoclaw/wechat-npm-cache/", - ); - const patchChmod = indexOfRequired( - finalStage, - "RUN chmod 755 /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts", - ); - const blueprintSetup = indexOfRequired( - finalStage, - "RUN mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0", - ); - const managedRuntimeDirectory = indexOfRequired( - finalStage, - "&& install -d -o root -g root -m 0755 /run/nemoclaw", - ); - const runtimeChmod = indexOfRequired(finalStage, "RUN chmod 755 /usr/local/bin/nemoclaw-start"); - - expect(dependency).toBeLessThan(tarPatch); - expect(tarPatch).toBeLessThan(braceExpansionPatch); - expect(braceExpansionPatch).toBeLessThan(ipAddressPatch); - expect(plugin).toBeGreaterThan(dependencyInstall); - expect(plugin).toBeLessThan(pluginChmod); - expect(managedMessagingUnionInstall).toBeLessThan(messagingPostInstall); - expect(messagingPostInstall).toBeLessThan(neutralConfigRegeneration); - expect(finalStage.slice(neutralConfigRegeneration)).toContain( - "openclaw config validate --json", - ); - expect(finalStage).toContain("packageManifest.openclaw?.channel?.id"); - expect(finalStage).toContain("if (!fs.existsSync(packagePath)) return []"); - expect(finalStage).toContain('channelId === "imessage"'); - expect(finalStage).toContain("bundled OpenClaw channel is not neutral"); - expect(patch).toBeGreaterThan(wechatInstall); - expect(patch).toBeLessThan(patchChmod); - expect(runtime).toBeGreaterThan(blueprintSetup); - expect(runtime).toBeLessThan(managedRuntimeDirectory); - expect(managedRuntimeDirectory).toBeLessThan(runtimeChmod); - expect(finalStage).toContain("/usr/local/bin/nemoclaw-managed-bootstrap"); - expect(dockerfile).toContain( - "COPY tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle /out/managed-startup-image-runtime.cjs", - ); - expect(dockerfile).not.toContain( - "COPY src/lib/onboard/managed-bootstrap/ ./src/lib/onboard/managed-bootstrap/", - ); - expect(runtime).toBeLessThan(runtimeChmod); - }); }); diff --git a/test/openclaw-lifecycle-policy.test.ts b/test/openclaw-lifecycle-policy.test.ts deleted file mode 100644 index d63a4d1fbbd..00000000000 --- a/test/openclaw-lifecycle-policy.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { spawnSync } from "node:child_process"; -import path from "node:path"; -import { describe, expect, it } from "vitest"; -import policy from "../ci/reviewed-npm-lifecycle-allowlist.json"; -import { reviewedOpenClawPluginIntegrityByPackageSpec } from "../src/lib/messaging/applier/build/messaging-build-applier.mts"; - -const REPO_ROOT = path.join(import.meta.dirname, ".."); -const PRODUCTION_BOUNDARY_AUDIT = String.raw` -const fs = require("node:fs"); -function between(source, startMarker, endMarker) { - const start = source.indexOf(startMarker); - const end = source.indexOf(endMarker, start + startMarker.length); - return start >= 0 && end > start ? source.slice(start, end) : ""; -} - -function corePackageSpecs(block) { - return [...block.matchAll( - /if \[ "\$OPENCLAW_VERSION" = "([0-9]+(?:\.[0-9]+){2})" \]; then EXPECTED_INTEGRITY=/g, - )].map((match) => "openclaw@" + match[1]).sort(); -} - -function explicitLifecycleScripts(block) { - const scripts = [...block.matchAll( - /^\s*([0-9]+(?:\.[0-9]+){2}(?:\|[0-9]+(?:\.[0-9]+){2})*)\)\s+(node [^;]+postinstall-bundled-plugins\.mjs)\s+;;/gm, - )].flatMap((match) => - match[1].split("|").map((version) => ({ - packageSpec: "openclaw@" + version, - explicitCommand: match[2], - })), - ); - const lockedRuntimeCommand = - "node /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/openclaw/scripts/postinstall-bundled-plugins.mjs"; - if ( - block.includes("npm --prefix /usr/local/lib/nemoclaw/openclaw-runtime ci") && - block.includes(lockedRuntimeCommand) - ) { - const manifest = JSON.parse( - fs.readFileSync("agents/openclaw/openclaw-runtime/package.json", "utf8"), - ); - scripts.push({ - packageSpec: "openclaw@" + manifest.dependencies.openclaw, - explicitCommand: lockedRuntimeCommand, - }); - } - return scripts.sort((left, right) => left.packageSpec.localeCompare(right.packageSpec)); -} - -const dockerfile = fs.readFileSync("Dockerfile", "utf8"); -const dockerfileBase = fs.readFileSync("Dockerfile.base", "utf8"); -const messagingApplier = fs.readFileSync( - "src/lib/messaging/applier/build/messaging-build-applier.mts", - "utf8", -); - -const codexBlock = between( - dockerfile, - "AS codex-acp-runtime", - "AS wechat-npm-cache", -); -const runtimeBlock = between( - dockerfile, - "# Upgrade OpenClaw if the base image is stale.", - "# Patch OpenClaw media fetch for proxy-only sandbox", -); -const baseBlock = between( - dockerfileBase, - "# Install OpenClaw CLI + PyYAML.", - "# Baseline health check.", -); -const optionalPluginBlock = between( - dockerfile, - "# Install non-messaging OpenClaw plugins that need to match the runtime.", - "# Lock down npm for the next RUN", -); -const messagingInstallBlock = between( - messagingApplier, - "export function installOpenClawMessagingPlugins", - "export function runOpenClawMessagingDoctor", -); - -const codexMatch = dockerfile.match( - /ADD --checksum=sha256:[0-9a-f]{64} https:\/\/registry\.npmjs\.org\/@zed-industries\/codex-acp\/-\/codex-acp-0\.11\.1\.tgz/, -); -const optionalPluginSpecs = [...optionalPluginBlock.matchAll( - /"(@openclaw\/[^"\s]+@[0-9]+(?:\.[0-9]+){2})"\)\s+expected_integrity=/g, - )].map((match) => match[1]).sort(); - -console.log(JSON.stringify({ - codexPackageSpec: codexMatch ? "@zed-industries/codex-acp@0.11.1" : null, - runtimeCoreSpecs: corePackageSpecs(runtimeBlock), - baseCoreSpecs: corePackageSpecs(baseBlock), - optionalPluginSpecs, - runtimeLifecycleScripts: explicitLifecycleScripts(runtimeBlock), - baseLifecycleScripts: explicitLifecycleScripts(baseBlock), - scriptsSuppressed: { - codex: /npm install -g --offline --no-audit --no-fund --no-progress --ignore-scripts/.test(codexBlock), - runtime: /npm install -g --no-audit --no-fund --no-progress --ignore-scripts "\$OPENCLAW_PACK_PATH"/.test(runtimeBlock), - base: /npm install -g --ignore-scripts "\$OPENCLAW_PACK_PATH"/.test(baseBlock), - optionalPlugin: /NPM_CONFIG_IGNORE_SCRIPTS=true npm_config_ignore_scripts=true\s+\\\s*openclaw plugins install "npm-pack:/.test(optionalPluginBlock) && - optionalPluginBlock.includes('openclaw plugins install "npm-pack:\${plugin_install_archive}"'), - messagingPlugin: [ - '["openclaw", "plugins", "install", \`npm-pack:\${packed.archivePath}\`]', - 'NPM_CONFIG_IGNORE_SCRIPTS: "true"', - 'npm_config_ignore_scripts: "true"', - ].every((marker) => messagingInstallBlock.includes(marker)), - }, - legacyCoreRunsNoLifecycle: [runtimeBlock, baseBlock].every((block) => - /^\s*2026\.3\.11\)\s+;;/m.test(block), - ), - unknownCoreVersionFailsClosed: [runtimeBlock, baseBlock].every((block) => - /^\s*\*\).*no reviewed lifecycle policy.*exit 1/m.test(block), - ), -})); -`; - -describe("reviewed npm lifecycle policy", () => { - // source-shape-contract: security -- Every executable archive install must match the reviewed fail-closed lifecycle allowlist - it("cross-checks the allowlist against every production archive install boundary", () => { - expect(policy).toMatchObject({ schemaVersion: 1, defaultPolicy: "deny" }); - expect(policy.allowedLifecycleScripts).not.toHaveLength(0); - expect( - policy.allowedLifecycleScripts.every( - ({ event, manifestCommand }) => - event === "postinstall" && - manifestCommand === "node scripts/postinstall-bundled-plugins.mjs", - ), - ).toBe(true); - - const messagingPackageSpecs = Object.keys( - reviewedOpenClawPluginIntegrityByPackageSpec({ OPENCLAW_VERSION: "2026.7.1" }), - ); - const result = spawnSync(process.execPath, ["-e", PRODUCTION_BOUNDARY_AUDIT], { - cwd: REPO_ROOT, - encoding: "utf8", - }); - - expect(result.status, `${result.stdout}${result.stderr}`).toBe(0); - const audit = JSON.parse(result.stdout); - expect(audit.runtimeCoreSpecs).toEqual(audit.baseCoreSpecs); - expect( - [ - audit.codexPackageSpec, - ...audit.runtimeCoreSpecs, - ...audit.optionalPluginSpecs, - ...messagingPackageSpecs, - ].sort(), - ).toEqual([...policy.reviewedArchivePackages].sort()); - expect(audit.scriptsSuppressed).toEqual({ - codex: true, - runtime: true, - base: true, - optionalPlugin: true, - messagingPlugin: true, - }); - const allowedLifecycleScripts = policy.allowedLifecycleScripts - .map(({ packageSpec, explicitCommand }) => ({ packageSpec, explicitCommand })) - .sort((left, right) => left.packageSpec.localeCompare(right.packageSpec)); - expect(audit.runtimeLifecycleScripts).toEqual(audit.baseLifecycleScripts); - expect(audit.runtimeLifecycleScripts).toEqual(allowedLifecycleScripts); - expect(audit.legacyCoreRunsNoLifecycle).toBe(true); - expect(audit.unknownCoreVersionFailsClosed).toBe(true); - }); -}); diff --git a/test/openclaw-locked-install.test.ts b/test/openclaw-locked-install.test.ts index 70fb3ceb646..7f4dccc2048 100644 --- a/test/openclaw-locked-install.test.ts +++ b/test/openclaw-locked-install.test.ts @@ -313,54 +313,4 @@ describe("locked OpenClaw production installation (#5896)", () => { expect(verifyInstalledNpmLock(installedFixture({ omit: true, optional: true }))).toEqual([]); }); - // source-shape-contract: compatibility -- Both shipped Dockerfiles must preserve the reviewed lock verification and installation sequence - it.each([ - "Dockerfile", - "Dockerfile.base", - ])("invokes the locked installer before exposing OpenClaw in %s", (dockerfileName) => { - const contents = fs.readFileSync(path.join(REPO_ROOT, dockerfileName), "utf-8"); - const flattenedContents = contents.replace(/\\\s*\n/g, " ").replace(/\s+/g, " "); - const verifyIndex = contents.indexOf( - "node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-lock", - ); - const installIndex = contents.indexOf( - "npm --prefix /usr/local/lib/nemoclaw/openclaw-runtime ci", - verifyIndex, - ); - const installedIdentityIndex = contents.indexOf("--verify-installed-lock", installIndex); - const postinstallIndex = contents.indexOf( - "/usr/local/lib/nemoclaw/openclaw-runtime/node_modules/openclaw/scripts/postinstall-bundled-plugins.mjs", - installedIdentityIndex, - ); - const linkIndex = contents.indexOf( - "ln -s /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/openclaw", - postinstallIndex, - ); - const binLinkIndex = contents.indexOf( - "ln -s /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/.bin/openclaw", - linkIndex, - ); - const branchEnd = contents.indexOf("else \\", installIndex); - const currentInstallBranch = contents.slice(verifyIndex, branchEnd); - - const groupedRuntimeCopy = - "COPY agents/openclaw/openclaw-runtime/package.json agents/openclaw/openclaw-runtime/package-lock.json /usr/local/lib/nemoclaw/openclaw-runtime/"; - const splitLockCopy = - "COPY agents/openclaw/openclaw-runtime/package-lock.json /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json"; - expect(flattenedContents.includes(groupedRuntimeCopy) || contents.includes(splitLockCopy)).toBe( - true, - ); - expect(verifyIndex).toBeGreaterThanOrEqual(0); - expect(installIndex).toBeGreaterThan(verifyIndex); - expect(installedIdentityIndex).toBeGreaterThan(installIndex); - expect(postinstallIndex).toBeGreaterThan(installedIdentityIndex); - expect(linkIndex).toBeGreaterThan(postinstallIndex); - expect(binLinkIndex).toBeGreaterThan(linkIndex); - expect(branchEnd).toBeGreaterThan(installIndex); - expect(currentInstallBranch).toContain(`--lock-sha256 \"$OPENCLAW_LOCK_SHA256\"`); - expect(currentInstallBranch).not.toContain("npm install -g"); - expect(contents).toContain("'schema=4'"); - expect(contents).toContain('"lock-sha256=${OPENCLAW_LOCK_SHA256}"'); - expect(contents).toContain("locked-ci+reviewed-lifecycle-v2"); - }); }); diff --git a/test/openshell-0.0.101-migration-review.test.ts b/test/openshell-0.0.101-migration-review.test.ts index 342aace14c3..dd1f56de934 100644 --- a/test/openshell-0.0.101-migration-review.test.ts +++ b/test/openshell-0.0.101-migration-review.test.ts @@ -186,75 +186,6 @@ describe("OpenShell 0.0.101 migration review", () => { expect([...ranges.values()].reduce((sum, [commits]) => sum + commits, 0)).toBe(126); }); - // source-shape-contract: security -- Regenerated credential boundaries must retain exact reviewed upstream blobs and downstream sanitizers before any consumer activates the new manifest - it("binds the newly generated credential manifest to reviewed source identities (#8599)", () => { - expect(manifest.openshellVersion).toBe("0.0.101"); - expect(manifest.openshellCommit).toBe(SOURCE_COMMIT); - expect(manifest.sources).toEqual([ - "crates/openshell-core/src/google_cloud.rs", - "crates/openshell-core/src/provider_credentials.rs", - "crates/openshell-core/src/secrets.rs", - ]); - expect(manifest.nemoclawSources).toEqual([ - "src/lib/subprocess-env.ts", - "src/lib/actions/sandbox/mcp-bridge-validation.ts", - "agents/hermes/mcp-config-transaction.py", - ]); - expect(manifest.generation).toEqual({ - method: "openshell-static-config-and-child-env-source-review-v1", - upstreamSourceEvidence: [ - { - path: "crates/openshell-core/src/google_cloud.rs", - gitObjectId: "fcab45ae086ea7b45a7326b46ceb849c8f115474", - sha256: "2583a04a0557f0694f405cbd28d8ea730a74d8a8e6bc952fd9ce5f763f13ac24", - }, - { - path: "crates/openshell-core/src/provider_credentials.rs", - gitObjectId: "d0b7b38ad5ad85efd17edefe33148c1368de8082", - sha256: "e16124481e16616592f41131b31f9d5e674c1eeb3d496e3a50a959b39c70ae1e", - }, - { - path: "crates/openshell-core/src/secrets.rs", - gitObjectId: "e93bdc53900ae342e11a64f50a53b16ac75be256", - sha256: "f67c40cec776f49f49e4553d6e0477d27ca771944afc7fa677fd31cb3ccb7c37", - }, - ], - nemoclawSourceEvidence: [ - { - path: "src/lib/subprocess-env.ts", - sha256: "82f17b8d5b8e5fcc1e29f0393ff3739fc0a51f738120f19fe962a83f935ec70c", - }, - { - path: "src/lib/actions/sandbox/mcp-bridge-validation.ts", - sha256: "f78c6d05f2e93314b15901ad7169d46e3f9742ba04a36f53fc7be8753be9cfa4", - }, - { - path: "agents/hermes/mcp-config-transaction.py", - sha256: "88988d567fd297a1d37919ad269181a7b42059c5f80cf840477322252fc89351", - }, - ], - }); - - for (const evidence of manifest.generation?.nemoclawSourceEvidence ?? []) { - expect(sha256File(evidence.path), evidence.path).toBe(evidence.sha256); - } - for (const key of [ - "rawChildValueKeys", - "rewrittenChildValueKeys", - "runtimeControlKeys", - "runtimeControlPrefixes", - ] as const) { - expect(manifest[key], key).toEqual(previousManifest[key]); - } - expect(manifest.rawChildValueKeys).toHaveLength(8); - expect(manifest.rewrittenChildValueKeys).toHaveLength(3); - expect(manifest.runtimeControlKeys).toHaveLength(52); - expect(manifest.runtimeControlPrefixes).toHaveLength(24); - expect(previousManifest.generation).toBeUndefined(); - expect(review).toContain("was generated as a new"); - expect(review).toContain("issue `#8606`, not this review, owns changing active consumers"); - }); - it("selects only Docker or Podman without configuring new v0.0.101 surfaces (#8599)", () => { const untrustedNewSurfaceInputs = { OPENSHELL_CREDENTIAL_DRIVERS: "vault", diff --git a/test/openshell-0.0.99-migration-review.test.ts b/test/openshell-0.0.99-migration-review.test.ts index d2ef374d08c..c658ab48197 100644 --- a/test/openshell-0.0.99-migration-review.test.ts +++ b/test/openshell-0.0.99-migration-review.test.ts @@ -150,30 +150,6 @@ function parseDigestTable(start: string, end: string): DigestMatrix { } describe("OpenShell 0.0.99 migration review", () => { - // source-shape-contract: security -- Every shipped managed Docker policy must select sandbox:sandbox so suppressing OCI workspace preparation preserves the protected /sandbox owner - it("keeps every managed Docker policy identity explicit for workspace compatibility (#8662)", () => { - const ROOT = path.resolve(import.meta.dirname, ".."); - const policyPaths = [ - "nemoclaw-blueprint/policies/openclaw-sandbox.yaml", - "nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml", - "agents/openclaw/policy-permissive.yaml", - "agents/hermes/policy-additions.yaml", - "agents/hermes/policy-permissive.yaml", - "agents/langchain-deepagents-code/policy-additions.yaml", - ]; - - for (const policyPath of policyPaths) { - const policySource = fs.readFileSync(path.join(ROOT, policyPath), "utf8"); - const policy = YAML.parse(policySource) as { - process?: { run_as_user?: unknown; run_as_group?: unknown }; - }; - expect(policy.process, policyPath).toEqual({ - run_as_user: "sandbox", - run_as_group: "sandbox", - }); - } - }); - it("binds managed Docker activation to the v0.0.99 supervisor workdir argv (#8497)", () => { const authorityStore = {}; const launch = resolveOnboardManagedBootstrapLaunch({ @@ -234,38 +210,6 @@ describe("OpenShell 0.0.99 migration review", () => { expect(review).toContain("515 distinct changed paths"); }); - // source-shape-contract: security -- Exact release evidence must stay bound to the independently reviewed manifest identity and artifact digests. - it("associates every reviewed release identity with the 0.0.99 manifest (#8497)", () => { - expect( - parseDigestTable("Archive SHA-256 values are:", "Extracted binary SHA-256 values are:"), - ).toEqual(archiveDigests); - expect( - parseDigestTable("Extracted binary SHA-256 values are:", "The supervisor is pinned"), - ).toEqual(binaryDigests); - for (const digest of Object.values(SUPERVISOR_DIGESTS)) expect(review).toContain(digest); - - const manifest = JSON.parse( - fs.readFileSync( - path.join( - repoRoot, - "src/lib/actions/sandbox/openshell-child-visible-credentials.v0.0.99.json", - ), - "utf8", - ), - ) as { openshellCommit: string; openshellVersion: string; sources: string[] }; - expect(manifest.openshellCommit).toBe(SOURCE_COMMIT); - expect(manifest.openshellVersion).toBe("0.0.99"); - expect(manifest.sources).toEqual([ - "crates/openshell-core/src/google_cloud.rs", - "crates/openshell-core/src/provider_credentials.rs", - "crates/openshell-core/src/secrets.rs", - ]); - expect(review).toContain(SOURCE_COMMIT); - expect(pinnedOpenShellSandboxBuildVersion(binaryDigests.Sandbox[0])).toBe("0.0.99"); - expect(pinnedOpenShellSandboxBuildVersion(binaryDigests.Sandbox[1])).toBe("0.0.99"); - expect(pinnedOpenShellSandboxBuildVersion(binaryDigests.CLI[0])).toBeNull(); - }); - it("proves the exposed 0.0.99 compatibility contracts through behavior (#8497)", () => { expect( parseGatewayInference( diff --git a/test/pi-candidate-runtime-artifacts.test.ts b/test/pi-candidate-runtime-artifacts.test.ts index 7a1c7de7183..046fb34a4eb 100644 --- a/test/pi-candidate-runtime-artifacts.test.ts +++ b/test/pi-candidate-runtime-artifacts.test.ts @@ -162,167 +162,6 @@ describe("Pi release cohort separation", () => { expect(SHIPPED_MANAGED_IMAGE_AGENTS).not.toContain("pi"); }); - // source-shape-contract: security -- A published Pi candidate digest must never reach the atomic all-agent release cohort, and the artifact names are the only boundary between the two publication lanes - it("publishes candidate contracts outside the all-agent activation pattern", () => { - const workflow = YAML.parse(readRepoFile(".github/workflows/managed-images.yaml")) as { - jobs: Record> }>; - }; - const candidateSteps = workflow.jobs["pi-candidate"]?.steps ?? []; - const uploadNames = candidateSteps - .map((step) => (step.with as { name?: string } | undefined)?.name) - .filter((name): name is string => typeof name === "string"); - expect(uploadNames.some((name) => name.startsWith("managed-candidate-contract-"))).toBe(true); - expect(uploadNames.some((name) => name.startsWith("managed-pr-contract-"))).toBe(false); - const activationSteps = workflow.jobs["pr-managed-activation"]?.steps ?? []; - const downloadPatterns = activationSteps - .map((step) => (step.with as { pattern?: string } | undefined)?.pattern) - .filter((pattern): pattern is string => typeof pattern === "string"); - expect(downloadPatterns.some((pattern) => pattern.startsWith("managed-pr-contract-"))).toBe( - true, - ); - expect( - downloadPatterns.some((pattern) => pattern.startsWith("managed-candidate-contract-")), - ).toBe(false); - }); - - // source-shape-contract: security -- Pull-request candidate builds must not inherit package-write authority from the trusted publication job - it("does not grant package write permission to pull request candidate builds", () => { - const workflow = YAML.parse(readRepoFile(".github/workflows/managed-images.yaml")) as { - jobs: Record< - string, - { - if?: string; - permissions?: Record; - steps?: Array>; - } - >; - }; - const candidateJob = workflow.jobs["pi-candidate"]; - const publishJob = workflow.jobs["pi-candidate-publish"]; - expect(candidateJob?.if).toContain("github.event_name == 'pull_request'"); - expect(candidateJob?.permissions).toEqual({ contents: "read" }); - expect(publishJob?.if).toContain("github.event_name != 'pull_request'"); - expect(publishJob?.permissions).toEqual({ contents: "read", packages: "write" }); - expect(publishJob?.steps).toEqual(candidateJob?.steps); - }); - - // source-shape-contract: security -- Candidate and publication builds must import one digest-bound OCI base through a Buildx driver that supports digest-only outputs - it("imports the local base into Buildx for digest-only candidate publication", () => { - type WorkflowStep = { - id?: string; - name?: string; - run?: string; - with?: Record; - }; - const workflow = YAML.parse(readRepoFile(".github/workflows/managed-images.yaml")) as { - jobs: Record; - }; - const steps = workflow.jobs["pi-candidate"]?.steps ?? []; - const requiredStep = (name: string): WorkflowStep => { - const selected = steps.find((step) => step.name === name); - expect(selected, `missing workflow step: ${name}`).toBeDefined(); - return selected ?? {}; - }; - - const buildx = requiredStep("Set up Docker Buildx"); - expect(buildx.id).toBe("buildx"); - expect(buildx.with?.["driver"]).not.toBe("docker"); - - const baseBuild = requiredStep("Build the exact Pi candidate base").run ?? ""; - expect(baseBuild).toContain('--output "type=docker,dest=${local_base_archive}"'); - expect(baseBuild).toContain('--output "type=oci,dest=${local_base_oci_archive}"'); - expect(baseBuild).toContain('docker load --input "$local_base_archive"'); - expect(baseBuild).toContain('tar -C "$local_base_oci" -xf "$local_base_oci_archive"'); - expect(baseBuild).toContain("if length == 1 then .[0].digest"); - expect(baseBuild).toContain( - 'printf \'oci=%s@%s\\n\' "$local_base_oci" "$local_base_oci_digest"', - ); - - const expectedContext = "nemoclaw-pi-base=oci-layout://${{ steps.base.outputs.oci }}"; - for (const name of [ - "Build the Pi candidate managed image", - "Publish the Pi candidate image by digest", - ]) { - const build = requiredStep(name); - expect(build.with?.builder).toBe("${{ steps.buildx.outputs.name }}"); - expect(build.with?.["build-contexts"]).toBe(expectedContext); - expect(build.with?.["build-args"]).toContain("BASE_IMAGE=nemoclaw-pi-base"); - } - expect(requiredStep("Publish the Pi candidate image by digest").with?.outputs).toContain( - "push-by-digest=true", - ); - }); - - // source-shape-contract: security -- Pull-request and published-digest qualification must bind the declared OCI entrypoint and empty command to the held-state contract - it("qualifies local and published candidates through the declared entrypoint", () => { - const workflow = readRepoFile(".github/workflows/managed-images.yaml"); - const dockerfile = readRepoFile("agents/pi/Dockerfile"); - const entrypointStep = workflow.slice( - workflow.indexOf("- name: Exercise the Pi candidate through its declared entrypoint"), - workflow.indexOf("- name: Record the exact Pi candidate contract"), - ); - expect(entrypointStep).not.toContain("if: github.event_name"); - expect(entrypointStep).toContain("EVENT_NAME: ${{ github.event_name }}"); - expect(entrypointStep).toContain( - "IMAGE_REFERENCE: nemoclaw-managed-candidate/pi:${{ github.sha }}", - ); - expect(entrypointStep).toContain('if [ "$EVENT_NAME" = "pull_request" ]; then'); - expect(entrypointStep).toContain('reference="$IMAGE_REFERENCE"'); - const publishedReference = 'reference="$' + "{REPOSITORY}@$" + '{DIGEST}"'; - expect(entrypointStep).toContain(publishedReference); - expect(entrypointStep).not.toContain("--entrypoint /usr/local/bin/nemoclaw-start"); - expect(dockerfile).toContain('ENTRYPOINT ["/usr/local/bin/nemoclaw-start"]'); - expect(dockerfile).toContain("CMD []"); - expect(dockerfile).not.toContain('CMD ["/bin/bash"]'); - expect(entrypointStep).toContain("openssl req -x509 -newkey rsa:2048"); - expect(entrypointStep).toContain("dst=/usr/local/share/nemoclaw/corporate-ca.pem,readonly"); - expect(entrypointStep).toContain("docker exec --user 999:999"); - for (const name of [ - "SSL_CERT_FILE", - "CURL_CA_BUNDLE", - "REQUESTS_CA_BUNDLE", - "GIT_SSL_CAINFO", - "NODE_EXTRA_CA_CERTS", - ]) { - expect(entrypointStep).toContain(name); - } - expect(entrypointStep).toContain("source /tmp/nemoclaw-proxy-env.sh"); - expect(entrypointStep).toContain( - "for proxy_variable in HTTP_PROXY HTTPS_PROXY http_proxy https_proxy", - ); - expect(entrypointStep).toContain("for no_proxy_variable in NO_PROXY no_proxy"); - expect(entrypointStep).toContain("merged_ca=/tmp/nemoclaw-ca-bundle.pem"); - expect(entrypointStep).toContain("merged_ca_status"); - expect(entrypointStep).toContain('!= "0:0:444"'); - expect(entrypointStep).toContain( - 'fs.readFileSync("/usr/local/share/nemoclaw/corporate-ca.pem")', - ); - expect(entrypointStep).toContain('fs.readFileSync(process.argv[1], "utf8")'); - expect(entrypointStep).toContain("new X509Certificate(block).fingerprint256"); - expect(entrypointStep).toContain("mounted.fingerprint256"); - }); - - // source-shape-contract: compatibility -- The accepted Pi launch matrix requires candidate qualification on both supported Linux architectures - it("builds and validates the candidate image for linux/amd64 and linux/arm64", () => { - const workflow = YAML.parse(readRepoFile(".github/workflows/managed-images.yaml")) as { - jobs: Record } } }>; - }; - const platforms = (workflow.jobs["pi-candidate"]?.strategy?.matrix?.include ?? []).map( - (entry) => entry.platform, - ); - expect(platforms).toEqual(["linux/amd64", "linux/arm64"]); - }); - - // source-shape-contract: compatibility -- The candidate image can only build on an architecture whose base image the publisher produces - it("publishes a Pi base image for linux/amd64 and linux/arm64", () => { - const workflow = YAML.parse(readRepoFile(".github/workflows/base-image.yaml")) as { - jobs: Record } } }>; - }; - const platforms = (workflow.jobs["build-pi-platforms"]?.strategy?.matrix?.include ?? []).map( - (entry) => entry.platform, - ); - expect(platforms).toEqual(["linux/amd64", "linux/arm64"]); - }); }); describe("Pi candidate contract validation", () => { @@ -358,53 +197,11 @@ describe("Pi runtime boundaries", () => { "/usr/local/lib/nemoclaw/pi-runtime/**", ]; - // source-shape-contract: security -- An agent-writable binary path in the baseline policy would give the agent an attacker-controlled egress channel - it("grants network capability only to the approved image-owned binaries", () => { - const policy = YAML.parse(readRepoFile("agents/pi/policy-additions.yaml")) as { - network_policies: Record }>; - }; - expect(Object.keys(policy.network_policies)).toEqual(["managed_inference"]); - const binaries = policy.network_policies.managed_inference.binaries ?? []; - expect(binaries.map((binary) => binary.path)).toEqual(APPROVED_MANAGED_INFERENCE_BINARY_PATHS); - }); - it("excludes an agent-writable binary path from the approved allowlist", () => { expect(APPROVED_MANAGED_INFERENCE_BINARY_PATHS).not.toContain("/tmp/agent-proxy"); expect(APPROVED_MANAGED_INFERENCE_BINARY_PATHS).not.toContain("/sandbox/agent-proxy"); }); - // source-shape-contract: security -- A corporate CA baked into the image but never merged into the runtime trust bundle leaves external TLS unverifiable through a corporate proxy - it("merges a baked corporate CA into the trust bundle Node reads", () => { - const startSh = readRepoFile("agents/pi/start.sh"); - expect(startSh).toContain("merge_corporate_proxy_ca"); - expect(startSh).toContain('export SSL_CERT_FILE="$_merged"'); - expect(startSh).toContain('export NODE_EXTRA_CA_CERTS="$_merged"'); - expect(startSh.indexOf("merge_corporate_proxy_ca()")).toBeLessThan( - startSh.indexOf("prepare_runtime_env()"), - ); - expect(startSh.indexOf("\nmerge_corporate_proxy_ca\n")).toBeLessThan( - startSh.indexOf("exec /usr/bin/setpriv"), - ); - expect(startSh).toContain('!= "0:0:444"'); - }); - - // source-shape-contract: security -- A merged CA variable that prepare_runtime_env does not persist is unavailable to independent login and exec shells, which read only the persisted runtime-env file - it("persists every merged CA variable into the runtime environment file", () => { - const startSh = readRepoFile("agents/pi/start.sh"); - const prepareRuntimeEnv = startSh.slice( - startSh.indexOf("prepare_runtime_env()"), - startSh.indexOf("\nprepare_runtime_env\n", startSh.indexOf("prepare_runtime_env()")), - ); - for (const name of [ - "SSL_CERT_FILE", - "CURL_CA_BUNDLE", - "REQUESTS_CA_BUNDLE", - "GIT_SSL_CAINFO", - "NODE_EXTRA_CA_CERTS", - ]) { - expect(prepareRuntimeEnv).toContain(`write_export_if_set ${name}`); - } - }); }); describe("Pi managed model catalog generation", () => { diff --git a/test/platform-vitest-main-workflow.test.ts b/test/platform-vitest-main-workflow.test.ts index 7f1b989ab9a..cb7802ed39e 100644 --- a/test/platform-vitest-main-workflow.test.ts +++ b/test/platform-vitest-main-workflow.test.ts @@ -36,218 +36,6 @@ describe("platform evidence workflow", () => { expect(run).toContain('test "$(git rev-parse --verify HEAD)" = "$GITHUB_SHA"'); expect(run.indexOf("safe.directory")).toBeLessThan(run.indexOf("npm run build:cli")); }); - // source-shape-contract: security -- The trusted helper installs only checksum-verified official Node.js archives - it("pins and verifies the Node.js archive in the trusted WSL helper", () => { - const installSteps = [{ run: wslHelperSource }]; - - for (const installStep of installSteps) { - expect(installStep, "missing WSL Node.js install step").toBeDefined(); - const run = installStep?.run ?? ""; - expect(run).toContain('node_version="22.23.2"'); - expect(run).toMatch( - /x86_64\)[\s\S]*?node_arch="x64"[\s\S]*?node_sha256="d60acfe00a2932254bb0ad20e01b0d74397a0875595de719654b214f4b03f307"[\s\S]*?;;/u, - ); - expect(run).toMatch( - /aarch64 \| arm64\)[\s\S]*?node_arch="arm64"[\s\S]*?node_sha256="fff4078c5def658577f92c88db7db3bc0072924bfb93fe52c1e744a54e94abb8"[\s\S]*?;;/u, - ); - expect(run).toContain( - 'node_url="https://nodejs.org/dist/v${node_version}/node-v${node_version}-linux-${node_arch}.tar.xz"', - ); - expect(run).toContain('temp_dir="$(mktemp -d)"'); - expect(run).toContain(`trap 'rm -rf "$temp_dir"' EXIT`); - expect(run).toContain("--proto '=https'"); - expect(run).toContain("--connect-timeout 15"); - expect(run).toContain("--max-time 180"); - expect(run).toContain("--retry 3"); - expect(run).toContain("--retry-max-time 240"); - expect(run).toContain("sha256sum --check --status"); - expect(run.indexOf("sha256sum --check --status")).toBeLessThan(run.indexOf("tar --extract")); - expect(run).toContain('test "$(node --version)" = "v${node_version}"'); - expect(run).toContain("Unsupported Node.js architecture"); - expect(run).not.toContain("deb.nodesource.com"); - expect(run).not.toMatch(/\bcurl\b[^\n]*\|\s*bash\b/u); - } - expect(step("wsl-vitest", "Install Node.js 22 in WSL").run).toContain("Install-WslNode"); - }); - - // source-shape-contract: security -- Sparse immutable helper checkouts must precede candidate code before root-capable WSL execution - it("loads the WSL helper from trusted revisions before candidate execution (#6958)", () => { - expect( - (workflow as Workflow & { on?: Record }).on, - "platform evidence workflow must not execute candidate code on pull requests", - ).not.toHaveProperty("pull_request"); - - const cases = [{ helperRef: "${{ github.workflow_sha }}", job: job("wsl-vitest") }]; - - for (const workflowCase of cases) { - expect(workflowCase.job, "missing WSL job").toBeDefined(); - const steps = workflowCase.job?.steps ?? []; - const trustedCheckout = steps.find( - (entry) => entry.name === "Check out the trusted WSL helper", - ); - const candidateCheckout = steps.find((entry) => entry.name === "Check out candidate source"); - expect(trustedCheckout?.with).toMatchObject({ - ref: workflowCase.helperRef, - path: "trusted-wsl-ci", - "persist-credentials": false, - "sparse-checkout": `${WSL_HELPER_PATH}\n`, - "sparse-checkout-cone-mode": false, - }); - expect(candidateCheckout?.with).toMatchObject({ - path: "source", - "persist-credentials": false, - }); - expect(steps.map((entry) => entry.name)).not.toContain("Detect trusted WSL helper"); - expect(steps.map((entry) => entry.name)).not.toContain( - "Explain deferred trusted WSL helper rollout", - ); - expect( - steps.some((entry) => (entry.if ?? "").includes("steps.helper.outputs.present")), - "missing trusted helper must fail instead of skipping candidate validation", - ).toBe(false); - expect(steps.indexOf(trustedCheckout!)).toBeLessThan(steps.indexOf(candidateCheckout!)); - - for (const entry of steps.filter((candidate) => - /(?:Ensure|Install|Invoke|Sync)-Wsl/u.test(candidate.run ?? ""), - )) { - expect(entry.run, `${entry.name} must load the trusted helper`).toContain( - '. "$env:TRUSTED_WSL_HELPER"', - ); - } - } - - expect(readRepoText(WORKFLOW_PATH)).not.toMatch(/WriteAllText|wslpath|wsl\s+--install/u); - }); - - // source-shape-contract: compatibility -- macOS must use the same modern shell/tool semantics as the Linux sandbox fixtures - it("provisions the pinned macOS test runtime before running the full suite", () => { - const stepNames = job("macos-vitest").steps?.map((entry) => entry.name) ?? []; - const checkout = step("macos-vitest", "Checkout"); - const setupPython = step("macos-vitest", "Setup Python"); - const install = step("macos-vitest", "Install macOS test dependencies"); - const installOpenShell = step("macos-vitest", "Install pinned OpenShell"); - const run = install.run ?? ""; - - expect(job("macos-vitest")["timeout-minutes"]).toBe("${{ matrix.timeout_minutes }}"); - expect(job("macos-vitest").strategy).toMatchObject({ - "fail-fast": false, - matrix: { - include: [ - { shard: 1, timeout_minutes: 60 }, - { shard: 2, timeout_minutes: 30 }, - { shard: 3, timeout_minutes: 30 }, - { shard: 4, timeout_minutes: 30 }, - ], - }, - }); - expect(checkout.with).toMatchObject({ - "fetch-depth": 0, - "persist-credentials": false, - }); - expect(stepNames.indexOf("Setup Python")).toBeLessThan( - stepNames.indexOf("Install macOS test dependencies"), - ); - expect(stepNames.indexOf("Install macOS test dependencies")).toBeLessThan( - stepNames.indexOf("Install pinned OpenShell"), - ); - expect(stepNames.indexOf("Install pinned OpenShell")).toBeLessThan( - stepNames.indexOf("Run full Vitest suite on macOS"), - ); - expect(setupPython.uses).toBe("actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97"); - expect(setupPython.with).toMatchObject({ - "python-version": "3.14", - cache: "pip", - "cache-dependency-path": MACOS_REQUIREMENTS_PATH, - }); - for (const dependency of ["bash", "coreutils", "fd", "gawk", "ripgrep"]) { - expect(run).toMatch(new RegExp(`brew install[^\\n]*\\b${dependency}\\b`, "u")); - } - expect(run).toContain("$(brew --prefix bash)/bin"); - expect(run).toContain("$(brew --prefix coreutils)/libexec/gnubin"); - expect(run).toContain("$(brew --prefix gawk)/libexec/gnubin"); - expect(run).toContain("--only-binary=:all:"); - expect(run).toContain("--require-hashes"); - expect(run).toContain(`--requirement ${MACOS_REQUIREMENTS_PATH}`); - expect(installOpenShell.env).toMatchObject({ - NEMOCLAW_NON_INTERACTIVE: "1", - }); - expect(installOpenShell.run).toBe( - "env -u GH_TOKEN -u GITHUB_TOKEN bash scripts/install-openshell.sh", - ); - expect(step("macos-vitest", "Run full Vitest suite on macOS").run).toContain( - '--shard="${{ matrix.shard }}/4"', - ); - expect(step("macos-vitest", "Detect Docker availability for macOS E2E").if).toBe( - "${{ matrix.shard == 1 }}", - ); - expect(step("macos-vitest", "Run macOS live E2E").run).toContain( - "test/e2e/live/full-e2e.test.ts", - ); - - const requirements = readRepoText(MACOS_REQUIREMENTS_PATH); - expect(requirements).toContain("pyyaml==6.0.3"); - expect(requirements).toContain( - "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", - ); - expect(requirements).toContain("setuptools==82.0.1"); - expect(requirements).toContain( - "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", - ); - }); - - // source-shape-contract: security -- ordinary tests stay non-root while the five UID-0 contracts remain isolated - it("keeps the WSL suite unprivileged with explicit root-only contracts", () => { - const stepNames = job("wsl-vitest").steps?.map((entry) => entry.name) ?? []; - const checkout = step("wsl-vitest", "Check out candidate source"); - const install = step("wsl-vitest", "Install Ubuntu dependencies").run ?? ""; - const fullSuite = step("wsl-vitest", "Run full Vitest suite in WSL").run ?? ""; - const rootSuite = step("wsl-vitest", "Run root-required Vitest contracts in WSL").run ?? ""; - - expect(job("wsl-vitest")["timeout-minutes"]).toBe("${{ matrix.timeout_minutes }}"); - expect(job("wsl-vitest").strategy).toMatchObject({ - "fail-fast": false, - matrix: { - include: [ - { shard: 1, timeout_minutes: 180 }, - { shard: 2, timeout_minutes: 90 }, - { shard: 3, timeout_minutes: 90 }, - { shard: 4, timeout_minutes: 90 }, - ], - }, - }); - expect(checkout.with).toMatchObject({ - "fetch-depth": 0, - "persist-credentials": false, - }); - expect(stepNames.indexOf("Install Ubuntu dependencies")).toBeLessThan( - stepNames.indexOf("Run full Vitest suite in WSL"), - ); - expect(install).toContain("Install-WslUbuntuDependencies"); - expect(install).toContain("'python3-venv'"); - expect(install).toContain("'ripgrep'"); - expect(wslHelperSource).toContain("apt-get install -y $packageList"); - expect(install).not.toMatch(/\bsudo\b|sudoers|NOPASSWD/u); - expect(fullSuite).toContain("-User $env:WSL_TEST_USER"); - expect(fullSuite).toContain("NEMOCLAW_EXEC_TIMEOUT=60000"); - expect(fullSuite).toContain("NEMOCLAW_TEST_TIMEOUT=60000"); - expect(fullSuite).toContain("--shard='${{ matrix.shard }}/4'"); - expect(fullSuite).not.toMatch(/\bsudo\b|sudoers|NOPASSWD/u); - expect(rootSuite).toContain("-User root"); - expect(step("wsl-vitest", "Run root-required Vitest contracts in WSL").if).toBe( - "${{ matrix.shard == 1 }}", - ); - expect([...rootSuite.matchAll(/-t '([^']+)'/gu)].map((match) => match[1])).toEqual([ - "keeps the locked Hermes entry sticky-protected|lets a sandbox-group peer create state", - "requires both fixed files to match|reclaims a root-owned collapsed config|leaves a root-owned recovery baseline untouched", - ]); - expect(step("wsl-vitest", "Detect Docker availability in WSL").if).toBe( - "${{ matrix.shard == 1 }}", - ); - expect(step("wsl-vitest", "Run WSL live E2E").run).toContain( - "test/e2e/live/full-e2e.test.ts", - ); - }); - it("limits credentialed platform E2E to the first main-branch shard", () => { const cases = [ { diff --git a/test/plugin-vitest-project.test.ts b/test/plugin-vitest-project.test.ts index e0e0be23212..60f7d7ff968 100644 --- a/test/plugin-vitest-project.test.ts +++ b/test/plugin-vitest-project.test.ts @@ -7,17 +7,8 @@ import path from "node:path"; import { describe, expect, it } from "vitest"; -import standalonePluginVitestConfig from "../nemoclaw/vitest.config"; -import pluginVitestProjectOptions from "../nemoclaw/vitest.project"; -import rootVitestConfig from "../vitest.config"; - -type PolicyAlias = { - find: RegExp; - replacement: string; -}; const repositoryRoot = path.resolve(import.meta.dirname, ".."); -const fixtureUmaskSetup = "test/helpers/normalize-fixture-umask.ts"; const rootRequire = createRequire(path.join(repositoryRoot, "package.json")); const pluginRequire = createRequire(path.join(repositoryRoot, "nemoclaw", "package.json")); const pluginTypeScript = pluginRequire.resolve("typescript/bin/tsc"); @@ -38,73 +29,6 @@ function listedTypeScriptFiles(configPath: string): string[] { } describe("plugin Vitest project contract", () => { - // source-shape-contract: compatibility -- Root and standalone plugin runners must consume one canonical project contract - it("defines one canonical plugin project for root and standalone runs", () => { - const sourceTransform = pluginVitestProjectOptions.oxc; - const policyAliases = pluginVitestProjectOptions.test.alias as PolicyAlias[]; - const rootProjects = (rootVitestConfig.test?.projects ?? []) as unknown as Array<{ - test?: { name?: string }; - }>; - const rootPluginProjects = rootProjects.filter((project) => project.test?.name === "plugin"); - - expect(pluginVitestProjectOptions.root).toBe(repositoryRoot); - expect(sourceTransform.include).toEqual(/\.(?:[cm]?ts|[jt]sx)$/); - expect(pluginVitestProjectOptions.test.name).toBe("plugin"); - expect(pluginVitestProjectOptions.test.environment).toBe("node"); - expect(pluginVitestProjectOptions.test.env).toEqual({ - NEMOCLAW_DISABLE_GATEWAY_DRIFT_PREFLIGHT: "1", - }); - expect(pluginVitestProjectOptions.test.setupFiles).toEqual([fixtureUmaskSetup]); - expect(pluginVitestProjectOptions.test.include).toEqual(["nemoclaw/src/**/*.test.ts"]); - expect(policyAliases).toEqual([ - { - find: /^.*banner-boundary\.cjs$/, - replacement: path.join(repositoryRoot, "nemoclaw/src/shared/banner-boundary.cts"), - }, - { - find: /^.*openshell-policy-boundary\.cjs$/, - replacement: path.join(repositoryRoot, "nemoclaw/src/shared/openshell-policy-boundary.cts"), - }, - { - find: /^.*sandbox-name\.cjs$/, - replacement: path.join(repositoryRoot, "nemoclaw/src/shared/sandbox-name.cts"), - }, - { - find: /^.*snapshot-sanitizer-boundary\.cjs$/, - replacement: path.join( - repositoryRoot, - "nemoclaw/src/shared/snapshot-sanitizer-boundary.cts", - ), - }, - ]); - expect(pluginVitestProjectOptions.test).not.toHaveProperty("globalSetup"); - expect(rootPluginProjects).toEqual([pluginVitestProjectOptions]); - expect(standalonePluginVitestConfig).toEqual({ - ...pluginVitestProjectOptions, - test: { - ...pluginVitestProjectOptions.test, - globalSetup: path.join(repositoryRoot, "test/helpers/vitest-temp-root.ts"), - }, - }); - }); - - // source-shape-contract: compatibility -- Assertion enforcement must remain scoped to the expect-based plugin project - it("pilots assertion presence only in expect-based plugin tests (#6692)", () => { - const rootTest = rootVitestConfig.test as { - expect?: { requireAssertions?: boolean }; - projects?: Array<{ test?: { expect?: { requireAssertions?: boolean }; name?: string } }>; - }; - - expect(pluginVitestProjectOptions.test.expect).toEqual({ requireAssertions: true }); - expect(rootTest.expect?.requireAssertions).not.toBe(true); - const nonPluginProjects = (rootTest.projects ?? []).filter( - (project) => project.test?.name !== "plugin", - ); - for (const project of nonPluginProjects) { - expect(project.test?.expect?.requireAssertions, project.test?.name).not.toBe(true); - } - }); - it("keeps standalone plugin dependencies on the root Vitest toolchain", () => { for (const packageName of ["vitest", "vite"] as const) { expect(installedVersion(pluginRequire, packageName), packageName).toBe( diff --git a/test/pr-review-advisor-openshell-workflow-boundary.test.ts b/test/pr-review-advisor-openshell-workflow-boundary.test.ts index 3e2010747ca..8fba327529b 100644 --- a/test/pr-review-advisor-openshell-workflow-boundary.test.ts +++ b/test/pr-review-advisor-openshell-workflow-boundary.test.ts @@ -58,247 +58,6 @@ function validatePolicyMutation(mutate: (policy: Record) => void): } describe("PR review advisor OpenShell workflow boundary", () => { - // source-shape-contract: compatibility -- The selected target identity must reach host metadata preparation and the credential-free sandbox - it("binds host-prepared GitHub context to the selected repository and pull request", () => { - const workflow = YAML.parse(workflowSource()) as Record; - expect(workflow.jobs.review.env.TARGET_REPO).toBe( - "${{ github.event_name == 'pull_request_target' && github.repository || inputs.target_repo || github.repository }}", - ); - expect(workflow.jobs.review.env.PR_NUMBER).toBe( - "${{ github.event.pull_request.number || inputs.target_pr }}", - ); - - const missingIdentity = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - delete mutated.jobs.review.env.TARGET_REPO; - delete mutated.jobs.review.env.PR_NUMBER; - }), - ); - expect(missingIdentity).toEqual( - expect.arrayContaining([ - "review job env.TARGET_REPO must be ${{ github.event_name == 'pull_request_target' && github.repository || inputs.target_repo || github.repository }}", - "review job env.PR_NUMBER must be ${{ github.event.pull_request.number || inputs.target_pr }}", - ]), - ); - }); - - // source-shape-contract: security -- Executed and mounted trusted code plus the fallback PR worktree must stay on their pinned checkout paths - it("pins trusted helper and bind sources to their checkout directories", () => { - const workflow = YAML.parse(workflowSource()) as Record; - const defaultWorkdir = workflow.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Set default advisor workdir", - ); - expect(workflow.jobs.review.env.ADVISOR_DIR).toBe("${{ github.workspace }}/advisor"); - expect(workflow.jobs.publish.env.ADVISOR_DIR).toBe("${{ github.workspace }}/advisor"); - expect(defaultWorkdir).toMatchObject({ - if: "${{ github.event_name == 'workflow_dispatch' && inputs.target_repo == '' && inputs.target_pr == '' }}", - run: 'echo "ADVISOR_WORKDIR=$GITHUB_WORKSPACE/pr-workdir" >> "$GITHUB_ENV"', - }); - - const detachedSources = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - mutated.jobs.review.env.ADVISOR_DIR = "${{ github.workspace }}/pr-workdir/advisor"; - mutated.jobs.publish.env.ADVISOR_DIR = "${{ github.workspace }}/publish-artifacts/advisor"; - const defaultWorkdir = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Set default advisor workdir", - ); - defaultWorkdir.if = "${{ always() }}"; - defaultWorkdir.run = 'echo "ADVISOR_WORKDIR=$GITHUB_WORKSPACE/advisor" >> "$GITHUB_ENV"'; - }), - ); - expect(detachedSources).toEqual( - expect.arrayContaining([ - "review job env.ADVISOR_DIR must be ${{ github.workspace }}/advisor", - "publish job env.ADVISOR_DIR must be ${{ github.workspace }}/advisor", - "Set default advisor workdir must use the canonical dispatch-only condition", - "Set default advisor workdir must bind ADVISOR_WORKDIR to the fixed pr-workdir checkout", - ]), - ); - }); - - // source-shape-contract: security -- GitHub and model credentials must remain confined to distinct trusted host steps - it("keeps GitHub and upstream model credentials in separate host-only steps", () => { - const workflow = YAML.parse(workflowSource()) as Record; - const steps = workflow.jobs.review.steps as Array>; - const prepareInputs = steps.find((step) => step.name === "Prepare advisor sandbox inputs"); - const configure = steps.find((step) => step.name === "Configure OpenShell inference"); - const install = steps.find((step) => step.name === "Install OpenShell"); - const unavailable = steps.find((step) => step.name === "Write unavailable advisor artifacts"); - expect(prepareInputs?.env).toEqual({ GH_TOKEN: "${{ github.token }}" }); - expect(configure?.id).toBe("configure-openshell"); - expect(configure?.["continue-on-error"]).toBe(true); - expect(install?.if).toBe("${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS == '1' }}"); - expect(configure?.if).toBe("${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS == '1' }}"); - expect(configure?.env).toEqual({ - OPENAI_API_KEY: "${{ secrets.PR_REVIEW_ADVISOR_API_KEY }}", - }); - expect(unavailable).toMatchObject({ - id: "unavailable-analysis", - if: "${{ always() && steps.configure-openshell.outcome != 'success' }}", - env: { - BASE_REF: expect.any(String), - HEAD_REF: expect.any(String), - PR_REVIEW_ADVISOR_UNAVAILABLE_REASON: - "${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS == '0' && 'PR_REVIEW_ADVISOR_RUN_ANALYSIS=0' || 'OpenShell inference configuration failed or the advisor credential is unavailable' }}", - }, - run: 'node --experimental-strip-types --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/openshell.mts" unavailable', - }); - for (const name of [ - "Write unavailable advisor artifacts", - "Create credential-free advisor sandbox", - "Run PR review advisor", - "Download advisor artifacts from sandbox", - "Delete advisor sandbox", - ]) { - const serialized = JSON.stringify(steps.find((step) => step.name === name)); - expect(serialized, name).not.toContain("${{ github.token }}"); - expect(serialized, name).not.toContain("${{ secrets."); - } - - const inheritedCredentials = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - mutated.jobs.review.env.GH_TOKEN = "${{ github.token }}"; - mutated.jobs.review.env.PR_REVIEW_ADVISOR_API_KEY = - "${{ secrets.PR_REVIEW_ADVISOR_API_KEY }}"; - }), - ); - expect(inheritedCredentials).toContain( - "review job-level environment must not expose GitHub or model credentials", - ); - - const duplicateGitHubToken = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - const create = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Create credential-free advisor sandbox", - ); - create.env = { GH_TOKEN: "${{ github.token }}" }; - }), - ); - expect(duplicateGitHubToken).toEqual( - expect.arrayContaining([ - "only advisor sandbox input preparation may receive github.token", - "step 'Create credential-free advisor sandbox' must remain credential-free after OpenShell configuration", - ]), - ); - - const indirectCredential = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - const create = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Create credential-free advisor sandbox", - ); - create.env = { GH_TOKEN: "${{ env.FORWARDED_TOKEN }}" }; - }), - ); - expect(indirectCredential).toContain( - "step 'Create credential-free advisor sandbox' must remain credential-free after OpenShell configuration", - ); - - const bracketTokenExpression = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - const create = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Create credential-free advisor sandbox", - ); - create.env = { FORWARDED_TOKEN: "${{ github['token'] }}" }; - }), - ); - expect(bracketTokenExpression).toEqual( - expect.arrayContaining([ - "only advisor sandbox input preparation may receive github.token", - "step 'Create credential-free advisor sandbox' must remain credential-free after OpenShell configuration", - ]), - ); - - const duplicateModelSecret = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - const download = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Download advisor artifacts from sandbox", - ); - download.env = { - OPENAI_API_KEY: "${{ secrets.PR_REVIEW_ADVISOR_API_KEY }}", - }; - }), - ); - expect(duplicateModelSecret).toEqual( - expect.arrayContaining([ - "only OpenShell provider configuration may receive the advisor model credential", - "step 'Download advisor artifacts from sandbox' must remain credential-free after OpenShell configuration", - ]), - ); - - const combinedSecrets = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - const configureStep = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Configure OpenShell inference", - ); - configureStep.env.GH_TOKEN = "${{ github.token }}"; - const prepareStep = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Prepare advisor sandbox inputs", - ); - prepareStep.env.OPENAI_API_KEY = "${{ secrets.PR_REVIEW_ADVISOR_API_KEY }}"; - }), - ); - expect(combinedSecrets).toEqual( - expect.arrayContaining([ - "Prepare advisor sandbox inputs must receive only github.token", - "Configure OpenShell inference must receive only secrets.PR_REVIEW_ADVISOR_API_KEY as OPENAI_API_KEY", - "only OpenShell provider configuration may receive the advisor model credential", - "only advisor sandbox input preparation may receive github.token", - ]), - ); - }); - - // source-shape-contract: compatibility -- Manual dry runs must skip inference setup while retaining an auditable unavailable artifact - it("preserves credential-free unavailable artifacts for manual dry runs", () => { - const workflow = YAML.parse(workflowSource()) as Record; - expect(workflow.jobs.review.env.PR_REVIEW_ADVISOR_RUN_ANALYSIS).toBe( - "${{ github.event_name == 'workflow_dispatch' && inputs.run_analysis == false && '0' || '1' }}", - ); - - const verify = workflow.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Verify advisor analysis outcome", - ); - expect(verify.env.ANALYSIS_REQUESTED).toBe("${{ env.PR_REVIEW_ADVISOR_RUN_ANALYSIS }}"); - expect(verify.run).toContain('if [ "$ANALYSIS_REQUESTED" = "0" ]'); - - const weakenedDryRun = validateMutation((source) => - mutateWorkflowSource(source, (mutated) => { - mutated.jobs.review.env.PR_REVIEW_ADVISOR_RUN_ANALYSIS = "1"; - const install = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Install OpenShell", - ); - const configure = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Configure OpenShell inference", - ); - const unavailable = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Write unavailable advisor artifacts", - ); - const outcome = mutated.jobs.review.steps.find( - (step: { name?: string }) => step.name === "Verify advisor analysis outcome", - ); - delete install.if; - delete configure.if; - unavailable.if = "${{ steps.configure-openshell.outcome != 'success' }}"; - unavailable.env.PR_REVIEW_ADVISOR_UNAVAILABLE_REASON = "configuration failed"; - outcome.env.ANALYSIS_REQUESTED = "1"; - outcome.run = outcome.run.replace( - 'if [ "$ANALYSIS_REQUESTED" = "0" ]; then', - 'if [ "$ANALYSIS_REQUESTED" = "1" ]; then', - ); - }), - ); - expect(weakenedDryRun).toEqual( - expect.arrayContaining([ - "review job env.PR_REVIEW_ADVISOR_RUN_ANALYSIS must be ${{ github.event_name == 'workflow_dispatch' && inputs.run_analysis == false && '0' || '1' }}", - "Install OpenShell must run only when advisor analysis is requested", - "Configure OpenShell inference must run only when advisor analysis is requested", - "Write unavailable advisor artifacts must run after skipped or failed configuration", - "Write unavailable advisor artifacts must receive only refs and the canonical unavailable reason", - 'step \'Verify advisor analysis outcome\' run script must include if [ "$ANALYSIS_REQUESTED" = "0" ]', - "Verify advisor analysis outcome must use the trusted analysis request selector", - ]), - ); - }); - it("pins the OpenShell image, loopback gateway, and per-lane sandbox identity", () => { const errors = validateMutation((source) => mutateWorkflowSource(source, (workflow) => { @@ -385,53 +144,4 @@ describe("PR review advisor OpenShell workflow boundary", () => { ); }); - // source-shape-contract: security -- The no-egress hard-Landlock policy must keep mounted inputs immutable and isolate runtime writes - it("fails closed around the credential-free OpenShell filesystem and network boundary", () => { - const network = validatePolicyMutation((policy) => { - policy.network_policies = { - internet: { endpoints: ["https://example.com"] }, - }; - }); - expect(network).toContain("advisor OpenShell policy must not allow direct network egress"); - - const writableTrustedInputs = validatePolicyMutation((policy) => { - policy.filesystem_policy.read_write = ["/dev", "/advisor", "/pr-workdir"]; - }); - expect(writableTrustedInputs).toEqual( - expect.arrayContaining([ - "advisor OpenShell policy must retain only its writable runtime subtree", - "advisor OpenShell policy must not grant write access to /advisor", - "advisor OpenShell policy must not grant write access to /pr-workdir", - ]), - ); - - const extraWritablePath = validatePolicyMutation((policy) => { - policy.filesystem_policy.read_write.push("/sandbox"); - }); - expect(extraWritablePath).toContain( - "advisor OpenShell policy must not grant write access to /sandbox", - ); - - const broadReadPath = validatePolicyMutation((policy) => { - policy.filesystem_policy.read_only.push("/"); - }); - expect(broadReadPath).toContain("advisor OpenShell policy must not grant read access to /"); - - const missingInputAndRuntimeOrLandlock = validatePolicyMutation((policy) => { - policy.filesystem_policy.read_only = policy.filesystem_policy.read_only.filter( - (entry: string) => entry !== "/advisor", - ); - policy.filesystem_policy.read_write = policy.filesystem_policy.read_write.filter( - (entry: string) => entry !== "/sandbox/pr-review-advisor-runtime", - ); - policy.landlock.compatibility = "best_effort"; - }); - expect(missingInputAndRuntimeOrLandlock).toEqual( - expect.arrayContaining([ - "advisor OpenShell policy must grant read-only access to /advisor", - "advisor OpenShell policy must retain only its writable runtime subtree", - "advisor OpenShell policy must fail closed when Landlock is unavailable", - ]), - ); - }); }); diff --git a/test/release-latest-tag-workflow.test.ts b/test/release-latest-tag-workflow.test.ts index 8e28efc86dd..77e80aa9d6f 100644 --- a/test/release-latest-tag-workflow.test.ts +++ b/test/release-latest-tag-workflow.test.ts @@ -65,14 +65,6 @@ afterEach(() => { }); describe("release latest tag workflow", () => { - // source-shape-contract: security -- Exact verified-object output wiring prevents latest promotion from bypassing GitHub signature verification - it("binds latest promotion to the exact GitHub-verified tag object", () => { - expect(verifyStep?.uses).toBe("actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3"); - expect(moveStep?.env?.EXPECTED_RELEASE_TAG_OBJECT).toBe( - "${{ steps.verify-release-tag.outputs.tag_object_sha }}", - ); - }); - it("accepts a GitHub-verified signed tag and emits its exact object SHA", async () => { vi.stubEnv("RELEASE_TAG", RELEASE_TAG); const harness = createHarness({ verified: true, reason: "valid" }); diff --git a/test/runner.test.ts b/test/runner.test.ts index f5c2933a55b..6358b56de56 100644 --- a/test/runner.test.ts +++ b/test/runner.test.ts @@ -854,27 +854,6 @@ describe("regression guards", () => { }); describe("credential exposure guards (#429)", () => { - // source-shape-contract: security -- Executable walkthrough commands must never materialize the NVIDIA inference credential in child arguments - it("walkthrough.sh does not embed NVIDIA_INFERENCE_API_KEY in tmux or sandbox commands", () => { - const fs = require("fs"); - const src = fs.readFileSync( - path.join(import.meta.dirname, "..", "scripts", "walkthrough.sh"), - "utf-8", - ); - // Check only executable lines (tmux spawn, openshell connect) — not comments/docs - const cmdLines = src - .split("\n") - .filter( - (l: string) => - !l.trim().startsWith("#") && - !l.trim().startsWith("echo") && - (l.includes("tmux") || l.includes("openshell sandbox connect")), - ); - for (const line of cmdLines) { - expect(line.includes("NVIDIA_INFERENCE_API_KEY")).toBe(false); - } - }); - it("install-openshell.sh gh-absent path uses curl directly", () => { const scriptPath = path.join(import.meta.dirname, "..", "scripts", "install-openshell.sh"); const tmpBin = fs.mkdtempSync(path.join(os.tmpdir(), "gh-absent-")); diff --git a/test/runtime-provider-source-shape.test.ts b/test/runtime-provider-source-shape.test.ts deleted file mode 100644 index 9a5c1286cbb..00000000000 --- a/test/runtime-provider-source-shape.test.ts +++ /dev/null @@ -1,399 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { execFileSync } from "node:child_process"; -import { existsSync, readFileSync } from "node:fs"; -import { join } from "node:path"; -import { beforeAll, describe, expect, it } from "vitest"; - -const repoRoot = join(import.meta.dirname, ".."); -const byCodeUnit = (left: string, right: string): number => - left < right ? -1 : left > right ? 1 : 0; - -function trackedPaths(...pathspecs: readonly string[]): string[] { - return execFileSync("git", ["ls-files", "-z", "--", ...pathspecs], { - cwd: repoRoot, - encoding: "utf8", - }) - .split("\0") - .filter(Boolean) - .sort(byCodeUnit); -} - -const read = (relativePath: string): string => readFileSync(join(repoRoot, relativePath), "utf8"); -const isTestOnlySource = (path: string): boolean => - path.endsWith(".test.ts") || - path.endsWith(".test-support.ts") || - path.includes("/test/") || - path.startsWith("test/"); - -let productionPaths: string[] = []; -let bootstrapProtocolPaths: string[] = []; -let activationPaths: string[] = []; -let providerPaths: string[] = []; -let dockerfilePaths: string[] = []; -let packagingPaths: string[] = []; -const managedBootstrapLoad = - /(?:from\s*|import\s*|import\s*\(\s*|require\s*\(\s*)["']([^"']*managed-bootstrap(?:\/[^"']*)?)["']/giu; -const allowedManagedBootstrapLoad = - /\/managed-bootstrap\/(?:adapter|envelope|runtime-create)(?:\.[cm]?[jt]s)?$/u; -const packagedBootstrapAsset = - /(?:nemoclaw-managed-bootstrap|managed-bootstrap-trampoline|managed-startup-image-runtime\.cjs|nemoclaw-managed-startup-hold)/u; - -function disallowedManagedBootstrapLoads(source: string): string[] { - return [...source.matchAll(managedBootstrapLoad)] - .map((match) => match[1] ?? "") - .filter((specifier) => !allowedManagedBootstrapLoad.test(specifier)); -} - -beforeAll(() => { - productionPaths = trackedPaths( - "src/lib/onboard.ts", - "src/lib/onboard", - "scripts", - "agents", - ".github/workflows", - "Dockerfile", - "Dockerfile.base", - ); - bootstrapProtocolPaths = productionPaths.filter( - (path) => - path.startsWith("src/lib/onboard/managed-bootstrap/") && - path.endsWith(".ts") && - !path.endsWith(".test.ts"), - ); - activationPaths = productionPaths.filter( - (path) => - (path === "src/lib/onboard.ts" || path.startsWith("src/lib/onboard/")) && - path.endsWith(".ts") && - !isTestOnlySource(path) && - !path.startsWith("src/lib/onboard/managed-bootstrap/"), - ); - providerPaths = activationPaths.filter((path) => - path.startsWith("src/lib/onboard/runtime-provider/"), - ); - dockerfilePaths = productionPaths.filter((path) => /(?:^|\/)Dockerfile(?:\.base)?$/u.test(path)); - packagingPaths = productionPaths.filter( - (path) => - dockerfilePaths.includes(path) || - path.startsWith("scripts/") || - path.startsWith("agents/") || - path.startsWith(".github/workflows/"), - ); -}); - -describe("runtime provider central source boundary", () => { - // source-shape-contract: compatibility -- Migrated lifecycle and mutation consumers must stay provider-neutral while production selection excludes unqualified future providers and driver-specific bootstrap dependencies - it("keeps migrated provider identities and implementations behind the one bundle composition", () => { - const driverNeutralActions = { - "actions/inference-set.ts": read("src/lib/actions/inference-set.ts"), - "actions/sandbox/destroy-execution.ts": read("src/lib/actions/sandbox/destroy-execution.ts"), - "actions/sandbox/destroy.ts": read("src/lib/actions/sandbox/destroy.ts"), - "actions/sandbox/runtime/lifecycle-runtime.ts": read( - "src/lib/actions/sandbox/runtime/lifecycle-runtime.ts", - ), - "actions/sandbox/start.ts": read("src/lib/actions/sandbox/start.ts"), - "actions/sandbox/stop.ts": read("src/lib/actions/sandbox/stop.ts"), - }; - const onboardConsumers = { - "onboard/compute/plan.ts": read("src/lib/onboard/compute/plan.ts"), - "onboard/sandbox-registration.ts": read("src/lib/onboard/sandbox-registration.ts"), - "onboard/workload/runtime.ts": read("src/lib/onboard/workload/runtime.ts"), - }; - const providerContract = { - activation: read("src/lib/onboard/runtime-provider/activation.ts"), - contract: read("src/lib/onboard/runtime-provider/contract.ts"), - current: read("src/lib/onboard/runtime-provider/current.ts"), - docker: read("src/lib/onboard/runtime-provider/docker.ts"), - registry: read("src/lib/onboard/runtime-provider/registry.ts"), - }; - - for (const [name, source] of Object.entries(driverNeutralActions)) { - expect(source, `${name} must stay driver-neutral`).not.toMatch(/\b(?:docker|podman)\b/iu); - expect(source, `${name} must not import driver adapters`).not.toMatch( - /(?:adapters\/docker|docker-driver-sandbox-recovery)/u, - ); - } - for (const [name, source] of [ - ...Object.entries(driverNeutralActions), - ...Object.entries(onboardConsumers), - ]) { - expect(source, `${name} must not branch on a driver name`).not.toMatch( - /\b(?:openshellDriver|driverName)\s*={2,3}\s*["'][^"']+["']/u, - ); - expect(source, `${name} must not switch on a driver name`).not.toMatch( - /switch\s*\([^)]*\b(?:openshellDriver|driverName)\b[^)]*\)/u, - ); - } - expect(driverNeutralActions["actions/sandbox/start.ts"]).toMatch( - /resolved\.lifecycle\.verifyStarted\(/u, - ); - expect(providerContract.contract).toMatch( - /import type[\s\S]*from ["']\.\.\/managed-bootstrap\/runtime-create["']/u, - ); - expect([providerContract.current, providerContract.registry].join("\n")).not.toMatch( - /managed-bootstrap/u, - ); - expect(disallowedManagedBootstrapLoads(providerContract.docker)).toEqual([ - "../managed-bootstrap/docker-runtime", - ]); - expect(providerContract.current).not.toMatch(/\b(?:podman|mxc)\b/iu); - expect(providerContract.activation).not.toMatch(/\b(?:podman|mxc)\b/iu); - expect(providerContract.activation).not.toMatch( - /(?:providerId|driverName)\s*(?:===|!==)\s*["'](?:docker|podman|mxc)["']/iu, - ); - }); - - it("inventories every managed-bootstrap protocol source", () => { - expect(bootstrapProtocolPaths).toEqual([ - "src/lib/onboard/managed-bootstrap/adapter.ts", - "src/lib/onboard/managed-bootstrap/docker-authority-store.ts", - "src/lib/onboard/managed-bootstrap/docker-journal.ts", - "src/lib/onboard/managed-bootstrap/docker-runtime.ts", - "src/lib/onboard/managed-bootstrap/docker-shared-state.ts", - "src/lib/onboard/managed-bootstrap/docker-spec.ts", - "src/lib/onboard/managed-bootstrap/docker-test-fixture.ts", - "src/lib/onboard/managed-bootstrap/docker.ts", - "src/lib/onboard/managed-bootstrap/envelope.ts", - "src/lib/onboard/managed-bootstrap/image-runtime.ts", - "src/lib/onboard/managed-bootstrap/index.ts", - "src/lib/onboard/managed-bootstrap/managed-bootstrap-test-fixture.ts", - "src/lib/onboard/managed-bootstrap/podman-bootstrap-journal.ts", - "src/lib/onboard/managed-bootstrap/podman-bootstrap-replacement.ts", - "src/lib/onboard/managed-bootstrap/podman-held-workload.ts", - "src/lib/onboard/managed-bootstrap/podman-image-transaction.ts", - "src/lib/onboard/managed-bootstrap/podman-watcher-lease.ts", - "src/lib/onboard/managed-bootstrap/runtime-create.ts", - ]); - }); - - it("inventories every runtime-provider implementation", () => { - expect(providerPaths).toEqual([ - "src/lib/onboard/runtime-provider/access.ts", - "src/lib/onboard/runtime-provider/activation.ts", - "src/lib/onboard/runtime-provider/container-state-mutation.ts", - "src/lib/onboard/runtime-provider/contract.ts", - "src/lib/onboard/runtime-provider/current.ts", - "src/lib/onboard/runtime-provider/docker-llama-cpp-managed-lifecycle.ts", - "src/lib/onboard/runtime-provider/docker-llama-cpp-operation.ts", - "src/lib/onboard/runtime-provider/docker-llama-cpp-private-bridge-process.ts", - "src/lib/onboard/runtime-provider/docker-llama-cpp-private-bridge.ts", - "src/lib/onboard/runtime-provider/docker-operation-authority.ts", - "src/lib/onboard/runtime-provider/docker-state-mutation.ts", - "src/lib/onboard/runtime-provider/docker.ts", - "src/lib/onboard/runtime-provider/host-local-create-journal.ts", - "src/lib/onboard/runtime-provider/host-local-inference-lifecycle.ts", - "src/lib/onboard/runtime-provider/host-local-inference-routing.ts", - "src/lib/onboard/runtime-provider/host-local-inference.ts", - "src/lib/onboard/runtime-provider/mxc.ts", - "src/lib/onboard/runtime-provider/native-qualification-authority.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-host-local-inference.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-state-mutation.ts", - "src/lib/onboard/runtime-provider/podman.ts", - "src/lib/onboard/runtime-provider/registry.ts", - "src/lib/onboard/runtime-provider/snapshot.ts", - "src/lib/onboard/runtime-provider/state-mutation.ts", - ]); - }); - - // source-shape-contract: security -- Managed llama.cpp activation must remain behind the exact receipt-backed controller and operation-scoped Docker authority - it("activates Docker llama.cpp only through its durable lifecycle controller (#8433)", () => { - const docker = read("src/lib/onboard/runtime-provider/docker.ts"); - const adapter = read("src/lib/onboard/runtime-provider/docker-llama-cpp-managed-lifecycle.ts"); - const operation = read("src/lib/onboard/runtime-provider/docker-llama-cpp-operation.ts"); - const hostLocalContract = read("src/lib/onboard/runtime-provider/host-local-inference.ts"); - const podman = read("src/lib/onboard/runtime-provider/podman.ts"); - const installer = read("src/lib/inference/llama-cpp/managed-installer.ts"); - const localModelProfilePlan = read("src/lib/onboard/local-model-profile/plan.ts"); - const allTrackedPaths = trackedPaths("."); - expect(allTrackedPaths.filter((path) => !existsSync(join(repoRoot, path)))).toEqual([]); - const productionComposition = allTrackedPaths - .filter( - (path) => - /\.[cm]?ts$/u.test(path) && - !isTestOnlySource(path) && - path !== "src/lib/onboard/runtime-provider/docker-llama-cpp-managed-lifecycle.ts", - ) - .map(read) - .join("\n"); - expect(docker).toContain("createDockerLlamaCppHostLocalOperation"); - expect(docker).toMatch(/hostLocalInference:\s*\{[\s\S]*services:\s*\[["']llama-cpp["']\]/u); - expect(adapter).toContain("createDockerLlamaCppManagedLifecycle"); - expect(operation).toContain("createDockerLlamaCppManagedLifecycle"); - expect(installer).toContain("requireRuntimeProviderHostLocalInferenceOperation"); - expect(installer).not.toMatch(/(?:createDocker|docker-llama-cpp)/u); - expect(hostLocalContract).not.toMatch(/(?:Docker|Podman|createDocker)/u); - expect(podman).toContain("createPodmanHostLocalInferenceOperation"); - expect(podman).not.toContain("createDockerLlamaCppHostLocalOperation"); - expect(productionComposition).toContain("createDockerLlamaCppManagedLifecycle"); - expect(productionComposition).toContain("docker-llama-cpp-managed-lifecycle"); - expect(localModelProfilePlan).toContain( - 'export const LOCAL_MODEL_PROFILE_ENABLED_ENV = "NEMOCLAW_ENABLE_LOCAL_MODEL_PROFILE"', - ); - expect(localModelProfilePlan).toContain('export type LocalModelProfileRuntime = "vllm";'); - expect(localModelProfilePlan).not.toMatch(/LocalModelProfileRuntime\s*=\s*[^;]*llama-cpp/u); - }); - - it("inventories every production Dockerfile", () => { - expect(dockerfilePaths).toEqual([ - "Dockerfile", - "Dockerfile.base", - "agents/hermes/Dockerfile", - "agents/hermes/Dockerfile.base", - "agents/langchain-deepagents-code/Dockerfile", - "agents/langchain-deepagents-code/Dockerfile.base", - "agents/pi/Dockerfile", - "agents/pi/Dockerfile.base", - ]); - }); - - // source-shape-contract: security -- The central managed-bootstrap authority must stay driver-neutral so Docker, Podman, and MXC providers share one transaction contract - it("keeps the dormant managed-bootstrap protocol driver-neutral", () => { - const bootstrapProtocolSource = [ - read("src/lib/onboard/managed-bootstrap/adapter.ts"), - read("src/lib/onboard/managed-bootstrap/envelope.ts"), - read("src/lib/onboard/managed-bootstrap/index.ts"), - ].join("\n"); - const runtimeCreateContract = read("src/lib/onboard/managed-bootstrap/runtime-create.ts"); - expect(bootstrapProtocolSource).not.toMatch(/from\s+["'][^"']*(?:docker|podman)[^"']*["']/iu); - expect(bootstrapProtocolSource).not.toMatch( - /(?:driverId|providerId)\s*(?:===|!==)\s*["'](?:docker|podman)["']/iu, - ); - expect(bootstrapProtocolSource).not.toMatch(/\b(?:docker|podman|openshell|mxc)\b/iu); - expect(runtimeCreateContract).not.toMatch(/\b(?:docker|podman|mxc)\b/iu); - expect(runtimeCreateContract).not.toMatch( - /(?:driverId|providerId)\s*(?:===|!==)\s*["'][^"']+["']/iu, - ); - }); - - // source-shape-contract: security -- Central onboarding consumes the provider-neutral create contract while provider bundles own driver-specific bootstrap implementations - it("keeps central activation paths disconnected from driver bootstrap adapters", () => { - const onboardEntry = read("src/lib/onboard.ts"); - const activationSource = activationPaths - .filter((path) => !path.startsWith("src/lib/onboard/runtime-provider/")) - .map(read) - .join("\n"); - expect(disallowedManagedBootstrapLoads(onboardEntry)).toEqual([]); - expect(disallowedManagedBootstrapLoads(activationSource)).toEqual([]); - expect( - disallowedManagedBootstrapLoads( - [ - 'import type { Contract } from "../managed-bootstrap/adapter";', - 'import { envelope } from "../managed-bootstrap/envelope";', - 'import type { Lifecycle } from "../../managed-bootstrap/runtime-create.mts";', - ].join("\n"), - ), - ).toEqual([]); - expect( - disallowedManagedBootstrapLoads( - [ - 'import "../managed-bootstrap";', - 'import "../managed-bootstrap/index";', - 'import "../managed-bootstrap/docker-runtime";', - 'await import("../managed-bootstrap/podman-runtime");', - 'require("../managed-bootstrap/mxc-runtime");', - 'export { provider } from "../managed-bootstrap/future-provider";', - 'import type { Fake } from "../fake-managed-bootstrap/adapter";', - 'import type { Nested } from "../managed-bootstrap/docker/adapter";', - ].join("\n"), - ), - ).toEqual([ - "../managed-bootstrap", - "../managed-bootstrap/index", - "../managed-bootstrap/docker-runtime", - "../managed-bootstrap/podman-runtime", - "../managed-bootstrap/mxc-runtime", - "../managed-bootstrap/future-provider", - "../fake-managed-bootstrap/adapter", - "../managed-bootstrap/docker/adapter", - ]); - }); - - // source-shape-contract: security -- Qualified bootstrap implementations compose only inside their provider bundle; unqualified providers remain unsupported - it("composes Docker bootstrap locally while keeping Kubernetes unsupported", () => { - const dockerProvider = read("src/lib/onboard/runtime-provider/docker.ts"); - // Neutral contracts may name an operation but cannot activate a provider implementation. - const providerImplementationSource = providerPaths - .filter( - (path) => - path !== "src/lib/onboard/runtime-provider/contract.ts" && - path !== "src/lib/onboard/runtime-provider/docker.ts" && - path !== "src/lib/onboard/runtime-provider/persisted-engine-authority.ts", - ) - .map(read) - .join("\n"); - expect(providerImplementationSource).not.toMatch(/managed-bootstrap/iu); - expect(disallowedManagedBootstrapLoads(dockerProvider)).toEqual([ - "../managed-bootstrap/docker-runtime", - ]); - expect(dockerProvider).toMatch( - /bootstrap:\s*createDockerManagedBootstrapSurface\(providerId\)/u, - ); - expect(dockerProvider.match(/bootstrap:\s*unsupported\(/gu)).toHaveLength(1); - expect(dockerProvider.match(/recovery:\s*unsupported\(/gu)).toHaveLength(2); - }); - - // source-shape-contract: security -- Every managed image must package the same reviewed native boundary while provider activation remains independently gated - it("packages the dormant managed-bootstrap native boundary for every agent image", () => { - const entrypoint = read("scripts/managed-bootstrap-entrypoint.c"); - const trampoline = read("scripts/managed-bootstrap-trampoline.sh"); - const hold = read("scripts/managed-startup-hold.sh"); - const directE2e = read("scripts/checks/run-managed-image-direct-e2e.ts"); - const bootstrapRuntime = read("src/lib/onboard/managed-bootstrap/image-runtime.ts"); - const startupRuntime = read("src/lib/onboard/managed-startup/image-runtime.ts"); - const packagingSources = packagingPaths.map((path) => [path, read(path)] as const); - expect(entrypoint).toMatch(/exec_process\(NEMOCLAW_MANAGED_BOOTSTRAP_BASH/u); - expect(entrypoint).toMatch(/NEMOCLAW_MANAGED_BOOTSTRAP_FREESTANDING/u); - expect(trampoline).toMatch(/Non-executable image-owned bootstrap body/u); - expect(hold.startsWith("#!/bin/bash -p\n")).toBe(true); - expect(hold).toContain('[ "$7" = "--" ]'); - expect(hold).toContain("/usr/local/bin/nemoclaw-start"); - expect(directE2e).toContain("renderManagedBootstrapHeldCommand(request, bootstrapIdentity"); - expect(directE2e).toContain("...heldWorkloadArgv.slice(1)"); - expect(directE2e).toContain(`"--interactive"`); - expect(directE2e).toContain(`docker(["cp", "-"`); - expect(directE2e).toContain("input: serializeManagedBootstrapEnvelopeTar({"); - expect(directE2e).not.toContain("cat > ${MANAGED_BOOTSTRAP_REQUEST_FILE}"); - expect(directE2e).not.toContain("chown 0:0 ${MANAGED_BOOTSTRAP_REQUEST_FILE}"); - expect(directE2e).not.toMatch(/const HOLD\s*=/u); - expect(bootstrapRuntime.match(/require\.main === module/gu)).toHaveLength(1); - expect(startupRuntime).not.toMatch(/require\.main === module/u); - for (const dockerfilePath of [ - "Dockerfile", - "agents/hermes/Dockerfile", - "agents/langchain-deepagents-code/Dockerfile", - "agents/pi/Dockerfile", - ]) { - const dockerfile = read(dockerfilePath); - expect(dockerfile).toContain(" AS managed-bootstrap-entrypoint-builder"); - expect(dockerfile).toContain("COPY scripts/managed-bootstrap-entrypoint.c ./"); - expect(dockerfile).toContain( - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/bin/nemoclaw-managed-bootstrap /usr/local/bin/nemoclaw-managed-bootstrap", - ); - expect(dockerfile).toContain( - "COPY --from=managed-bootstrap-entrypoint-builder /out/usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh /usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh", - ); - } - expect( - packagingSources - .filter(([, source]) => packagedBootstrapAsset.test(source)) - .map(([path]) => path), - ).toEqual([ - ".github/workflows/managed-images.yaml", - "Dockerfile", - "agents/hermes/Dockerfile", - "agents/langchain-deepagents-code/Dockerfile", - "agents/pi/Dockerfile", - "scripts/checks/run-managed-image-direct-e2e.ts", - "scripts/managed-bootstrap-entrypoint.c", - "scripts/managed-bootstrap-trampoline.sh", - "scripts/managed-startup-hold.sh", - ]); - }); -}); diff --git a/test/source-architecture.test.ts b/test/source-architecture.test.ts index 379d3283210..da17152e5e0 100644 --- a/test/source-architecture.test.ts +++ b/test/source-architecture.test.ts @@ -20,19 +20,6 @@ function writeModule(root: string, file: string, source: string): void { fs.writeFileSync(destination, source); } -function listProductionTypeScriptFiles(directory: string): string[] { - return fs.readdirSync(directory, { withFileTypes: true }).flatMap((entry) => { - const entryPath = path.join(directory, entry.name); - return entry.isDirectory() - ? entry.name === "__test-helpers__" - ? [] - : listProductionTypeScriptFiles(entryPath) - : entry.isFile() && entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts") - ? [entryPath] - : []; - }); -} - function budget(overrides: Partial = {}): SourceArchitectureBudget { return { fanIn: { defaultMax: 10 }, @@ -55,20 +42,6 @@ describe("source architecture budget (#7692)", () => { expect(evaluateSourceArchitectureBudget(report, parsed)).toEqual([]); }); - // source-shape-contract: compatibility -- Removed step-mutation APIs must stay absent so step helpers cannot persist machine transitions - test("keeps removed step mutation APIs out of production source (#7703)", () => { - const productionSources = ["src/lib/onboard", "src/lib/state"] - .flatMap((directory) => listProductionTypeScriptFiles(path.join(REPO_ROOT, directory))) - .map((file) => fs.readFileSync(file, "utf8")); - - expect(productionSources.join("")).not.toMatch( - /LEGACY_MACHINE_STEP_MUTATION_OPTIONS|RecordOnly|onboard-step-mutation/, - ); - expect(fs.existsSync(path.join(REPO_ROOT, "src/lib/state/onboard-step-mutation.ts"))).toBe( - false, - ); - }); - test("rejects a new runtime cycle and names its files", ({ resources }) => { const root = resources.temporaryDirectory("nemoclaw-architecture-cycle-"); writeModule(root, "src/a.ts", 'import "./b";\n'); diff --git a/test/starter-prompt-docs.test.ts b/test/starter-prompt-docs.test.ts index d06b9e81701..37fc7081213 100644 --- a/test/starter-prompt-docs.test.ts +++ b/test/starter-prompt-docs.test.ts @@ -582,43 +582,6 @@ describe("starter prompt docs CTA", () => { } }); - // source-shape-contract: compatibility -- Docs entry points must generate the Starter Prompt before Fern validation and rendering - it("prepares the Starter Prompt in every docs build entry point (#5048)", () => { - const scripts = (JSON.parse(read("package.json")) as { scripts: Record }) - .scripts; - - expect(scripts["docs:sync-starter-prompt"]).toBe("tsx scripts/generate-starter-prompt.mts"); - expect(scripts["docs:prepare"]).toBe( - "npm run docs:sync-starter-prompt && tsx scripts/sync-agent-variant-docs.mts", - ); - expect(scripts["docs:sync-agent-variants"]).toBe("npm run docs:prepare"); - expect(scripts["docs:validate"]).toContain("npm run docs:check-starter-prompt"); - expect(scripts["docs:strict"]).toBe("npm run docs:prepare && npm run docs:validate"); - expect(scripts["docs:live"]).toMatch(/^npm run docs:prepare &&/); - - for (const workflowPath of [ - ".github/workflows/docs-preview-pr.yaml", - ".github/workflows/docs-publish-staging.yaml", - ".github/workflows/docs-publish-public.yaml", - ]) { - expect(read(workflowPath), `${workflowPath} prepares generated docs before Fern`).toContain( - "npm run docs:prepare", - ); - expect(read(workflowPath), `${workflowPath} validates generated docs before Fern`).toContain( - "npm run docs:validate", - ); - } - - for (const workflowPath of [ - ".github/workflows/docs-preview-pr.yaml", - ".github/workflows/docs-publish-staging.yaml", - ]) { - expect(read(workflowPath), `${workflowPath} runs when the generator changes`).toContain( - '- "scripts/generate-starter-prompt.mts"', - ); - } - }); - it("pins local credential capture to the checked-in helper and form (#5048)", () => { const promptSource = readStarterPrompt(); const formSource = fs.readFileSync(localCredentialFormSource, "utf8"); diff --git a/test/validate-blueprint.test.ts b/test/validate-blueprint.test.ts index 581fb6ae2c2..4165c467215 100644 --- a/test/validate-blueprint.test.ts +++ b/test/validate-blueprint.test.ts @@ -87,33 +87,7 @@ function allEndpoints(policy: SandboxPolicy): Endpoint[] { return Object.values(policy.network_policies ?? {}).flatMap((entry) => entry.endpoints ?? []); } -const bp = loadYaml(BLUEPRINT_PATH); - -describe("blueprint image trust anchor", () => { - // source-shape-contract: security -- The immutable sandbox image digest is the executable supply-chain trust anchor - it("pins the sandbox image by digest instead of a mutable tag (#1438)", () => { - const sandbox = bp.components?.sandbox; - const image = typeof sandbox?.image === "string" ? sandbox.image : ""; - - expect(image.length).toBeGreaterThan(0); - expect(image).toContain("@sha256:"); - expect(image).not.toMatch(/:latest$/); - expect(image).not.toMatch(/:latest@/); - expect(image.match(/@sha256:([0-9a-f]{64})$/)).not.toBeNull(); - }); - - // source-shape-contract: security -- Cross-field digest equality prevents the shipped sandbox trust anchor from drifting - it("populates the top-level digest field with the image digest (#1438)", () => { - const topLevelDigest = typeof bp.digest === "string" ? bp.digest : ""; - const image = - typeof bp.components?.sandbox?.image === "string" ? bp.components.sandbox.image : ""; - const imageDigestMatch = image.match(/@sha256:([0-9a-f]{64})$/); - expect(topLevelDigest).toMatch(/^sha256:[0-9a-f]{64}$/); - expect(imageDigestMatch).not.toBeNull(); - expect(topLevelDigest).toBe(`sha256:${imageDigestMatch?.[1] ?? ""}`); - }); -}); describe("effective sandbox policy behavior", () => { it("keeps default OpenClaw egress least-privilege after create-policy preparation", () => { diff --git a/test/vitest-coverage-thresholds.test.ts b/test/vitest-coverage-thresholds.test.ts index 3c84e1bf0bd..6e0e5b23b1c 100644 --- a/test/vitest-coverage-thresholds.test.ts +++ b/test/vitest-coverage-thresholds.test.ts @@ -16,67 +16,6 @@ type RootTestOptions = { }; describe("Vitest security coverage thresholds", () => { - // source-shape-contract: security -- Exact per-file floors are executable security regression gates for merged coverage - it("enforces the exact per-file security floors for full and merged coverage (#6692)", () => { - expect(resolveVitestCoverageThresholds([])).toEqual({ - perFile: true, - "nemoclaw/src/blueprint/ssrf.ts": { - lines: 95, - functions: 100, - branches: 95, - statements: 95, - }, - "src/lib/inference/endpoint-ssrf-preflight.ts": { - lines: 76, - functions: 80, - branches: 69, - statements: 75, - }, - "src/lib/security/{credential-filter,redact,redact-url}.ts": { - lines: 80, - functions: 70, - branches: 65, - statements: 80, - }, - "src/commands/sandbox/policy/{add,remove}.ts": { - lines: 100, - functions: 100, - branches: 100, - statements: 100, - }, - "src/lib/policy/{commands,merge}.ts": { - lines: 100, - functions: 100, - branches: 100, - statements: 100, - }, - "src/lib/inference/gateway-route-mutation-lock.ts": { - lines: 100, - functions: 100, - branches: 65, - statements: 80, - }, - "src/lib/shields/transition-lock.ts": { - lines: 70, - functions: 60, - branches: 60, - statements: 65, - }, - "src/lib/state/mcp-lifecycle-lock-{acquisition,identity,storage}.ts": { - lines: 60, - functions: 75, - branches: 60, - statements: 60, - }, - }); - expect(resolveVitestCoverageThresholds(["--mergeReports", ".vitest-reports"])).toBe( - securityCoverageThresholds, - ); - expect((rootVitestConfig.test as RootTestOptions).coverage?.thresholds).toBe( - securityCoverageThresholds, - ); - }); - it.each([ ["inline", ["--coverage", "--shard=1/8"]], ["separate", ["--coverage", "--shard", "1/8"]], diff --git a/test/vitest-developer-feedback.test.ts b/test/vitest-developer-feedback.test.ts index ac65947e880..ee8462d227e 100644 --- a/test/vitest-developer-feedback.test.ts +++ b/test/vitest-developer-feedback.test.ts @@ -3,39 +3,22 @@ import { describe, expect } from "vitest"; -import rootVitestConfig from "../vitest.config"; import { test as it } from "./helpers/owned-test-resources"; import { resolveVitestFeedback } from "./helpers/vitest-feedback"; import { runVitestNpmScript } from "./helpers/vitest-npm-script"; -type RootTestOptions = { - reporters?: unknown; - silent?: boolean | "passed-only"; -}; - const focusedProjects = "--project cli --project plugin --project e2e-support"; describe("Vitest developer feedback", () => { - // source-shape-contract: compatibility -- Root Vitest feedback must preserve CI failure logs while deferring reporter selection - it("lets Vitest select reporters and preserves failed-test logs in CI (#6692)", () => { - const testOptions = rootVitestConfig.test as RootTestOptions; - - expect(testOptions).not.toHaveProperty("reporters"); + it("selects passed-only output for CI (#6692)", () => { expect(resolveVitestFeedback({})).toEqual({ isCi: false, silent: false }); expect(resolveVitestFeedback({ CI: "0" })).toEqual({ isCi: false, silent: false }); - expect(resolveVitestFeedback({ CI: "1" })).toEqual({ - isCi: true, - silent: "passed-only", - }); - expect(resolveVitestFeedback({ CI: "true" })).toEqual({ - isCi: true, - silent: "passed-only", - }); + expect(resolveVitestFeedback({ CI: "1" })).toEqual({ isCi: true, silent: "passed-only" }); + expect(resolveVitestFeedback({ CI: "true" })).toEqual({ isCi: true, silent: "passed-only" }); expect(resolveVitestFeedback({ GITHUB_ACTIONS: "true" })).toEqual({ isCi: true, silent: "passed-only", }); - expect(testOptions.silent).toBe(resolveVitestFeedback().silent); }); it("runs changed and watch feedback on the focused source projects (#6692)", ({ resources }) => { diff --git a/test/vitest-state-isolation.test.ts b/test/vitest-state-isolation.test.ts deleted file mode 100644 index 3bdaba85dd3..00000000000 --- a/test/vitest-state-isolation.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { describe, expect, it } from "vitest"; - -import standalonePluginVitestConfig from "../nemoclaw/vitest.config"; -import pluginVitestProjectOptions from "../nemoclaw/vitest.project"; -import rootVitestConfig from "../vitest.config"; -import { vitestStateIsolation } from "./helpers/vitest-state-isolation"; - -type ProjectTestOptions = Partial & { - mockReset?: boolean; - name?: string; -}; - -const DETERMINISTIC_PROJECTS = [ - "cli", - "integration", - "installer-integration", - "package-contract", - "plugin", - "e2e-support", -] as const; - -const LIVE_PROJECTS = ["e2e-live"] as const; - -const AUTOMATIC_CLEANUP_OPTIONS = [ - "clearMocks", - "restoreMocks", - "unstubEnvs", - "unstubGlobals", - "mockReset", -] as const; - -function projectTestOptions(): ProjectTestOptions[] { - const projects = (rootVitestConfig.test?.projects ?? []) as unknown as Array<{ - test?: ProjectTestOptions; - }>; - return projects.flatMap((project) => (project.test ? [project.test] : [])); -} - -describe("Vitest state isolation", () => { - it("enables automatic state cleanup in every deterministic project", () => { - const projects = projectTestOptions(); - - for (const name of DETERMINISTIC_PROJECTS) { - const project = projects.find((candidate) => candidate.name === name); - expect(project, name).toMatchObject(vitestStateIsolation); - expect(project?.mockReset, name).not.toBe(true); - } - }); - - // source-shape-contract: security -- Live and root runners must not enable unvalidated automatic state cleanup - it("keeps root and live projects free of unvalidated automatic cleanup", () => { - const projects = projectTestOptions(); - const rootOptions = rootVitestConfig.test as ProjectTestOptions; - - for (const option of AUTOMATIC_CLEANUP_OPTIONS) { - expect(rootOptions, `root.${option}`).not.toHaveProperty(option); - } - - for (const name of LIVE_PROJECTS) { - const project = projects.find((candidate) => candidate.name === name); - expect(project, name).toBeDefined(); - for (const option of AUTOMATIC_CLEANUP_OPTIONS) { - expect(project, `${name}.${option}`).not.toHaveProperty(option); - } - } - }); - - // source-shape-contract: compatibility -- Standalone plugin execution must share deterministic cleanup without mock reset - it("keeps standalone plugin runs aligned without enabling mockReset", () => { - expect(pluginVitestProjectOptions.test).toMatchObject(vitestStateIsolation); - expect(standalonePluginVitestConfig.test).toMatchObject(vitestStateIsolation); - expect(pluginVitestProjectOptions.test).not.toHaveProperty("mockReset", true); - expect(standalonePluginVitestConfig.test).not.toHaveProperty("mockReset", true); - }); -}); diff --git a/test/vitest-temp-root.test.ts b/test/vitest-temp-root.test.ts index 01deb8be61f..0148a2626f3 100644 --- a/test/vitest-temp-root.test.ts +++ b/test/vitest-temp-root.test.ts @@ -7,16 +7,12 @@ import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; -import pluginVitestConfig from "../nemoclaw/vitest.config"; -import rootVitestConfig from "../vitest.config"; import { prepareGitHubHostedRuntimeAuthority, setupVitestTempRoot, } from "./helpers/vitest-temp-root"; const TEMP_ENV_KEYS = ["TMPDIR", "TMP", "TEMP"] as const; -const ROOT_SETUP = "test/helpers/vitest-temp-root.ts"; -const STATE_SETUP = "test/helpers/isolate-test-state.ts"; type TempEnv = Record<(typeof TEMP_ENV_KEYS)[number], string | undefined>; @@ -282,33 +278,5 @@ describe("Vitest temp root", () => { } }); - // source-shape-contract: compatibility -- Root and standalone runners must install the shared temporary-root cleanup boundary - it("wires cleanup into root and standalone plugin test runs", () => { - expect(rootVitestConfig.test?.globalSetup).toBe(ROOT_SETUP); - expect(pluginVitestConfig.test?.globalSetup).toBe( - path.resolve(import.meta.dirname, "..", ROOT_SETUP), - ); - }); - - // source-shape-contract: security -- Non-live state isolation must never redirect credential-bearing live E2E state - it("isolates stateful non-live projects without redirecting live E2E state", () => { - const projects = (rootVitestConfig.test?.projects ?? []) as Array<{ - test?: { name?: string; setupFiles?: string[] }; - }>; - const setupFilesByProject = new Map( - projects.map((project) => [project.test?.name, project.test?.setupFiles ?? []]), - ); - for (const name of [ - "cli", - "integration", - "installer-integration", - "package-contract", - "e2e-support", - ]) { - expect(setupFilesByProject.get(name), name).toContain(STATE_SETUP); - } - expect(setupFilesByProject.get("plugin")).not.toContain(STATE_SETUP); - expect(setupFilesByProject.get("e2e-live")).not.toContain(STATE_SETUP); - }); }); diff --git a/test/vitest-watch-triggers.test.ts b/test/vitest-watch-triggers.test.ts index df9cc3f58c2..d71e15ccb24 100644 --- a/test/vitest-watch-triggers.test.ts +++ b/test/vitest-watch-triggers.test.ts @@ -6,7 +6,6 @@ import path from "node:path"; import { describe, expect, it } from "vitest"; -import rootVitestConfig from "../vitest.config"; import { resolveVitestWatchTests, vitestWatchTriggerPatterns, @@ -85,11 +84,6 @@ function triggeredBy(relativePath: string): string[] { } describe("Vitest opaque-input watch triggers", () => { - // source-shape-contract: compatibility -- Root watch mode must install the canonical opaque-input trigger resolver - it("registers the focused mappings at the root configuration boundary (#6692)", () => { - expect(rootVitestConfig.test?.watchTriggerPatterns).toBe(vitestWatchTriggerPatterns); - }); - it("maps current opaque inputs to their direct contract tests (#6692)", () => { expect(triggeredBy("managed-inference/recipes/vllm.example.managed-cluster.v1.yaml")).toEqual([ "src/lib/inference/serving/catalog.test.ts", From 21cced6f49c9d2b8f3e887922fcf0979cd038e3f Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 11:02:22 -0700 Subject: [PATCH 2/6] docs: update deleted test references --- src/lib/inference/nvidia-featured-models.ts | 6 +++--- src/lib/onboard/managed-bootstrap/README.md | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/lib/inference/nvidia-featured-models.ts b/src/lib/inference/nvidia-featured-models.ts index d0b528eec04..6c0b012014f 100644 --- a/src/lib/inference/nvidia-featured-models.ts +++ b/src/lib/inference/nvidia-featured-models.ts @@ -10,9 +10,9 @@ export const NVIDIA_FEATURED_MODELS_URL = "https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json"; // NVIDIA Endpoints retirement contract: the public featured feed and // authenticated /models catalog can lag a runtime retirement. The repository -// authority is CLOUD_MODEL_OPTIONS plus the provider-boundary assertion in -// test/inference-options-docs.test.ts, which keeps independently available -// Hermes Provider models separate from NVIDIA Endpoints choices. Keep entries +// authority is CLOUD_MODEL_OPTIONS. nvidia-featured-models.test.ts verifies +// that the NVIDIA picker excludes retired entries, and config.test.ts verifies +// that Hermes Provider retains its independent model catalog. Keep entries // in this policy deny-list until a deliberate product change confirms that the // NVIDIA chat-completions route is available again or names a live successor. const RETIRED_NVIDIA_FEATURED_MODEL_IDS = new Set([ diff --git a/src/lib/onboard/managed-bootstrap/README.md b/src/lib/onboard/managed-bootstrap/README.md index 937b5e64922..9e4af7401b1 100644 --- a/src/lib/onboard/managed-bootstrap/README.md +++ b/src/lib/onboard/managed-bootstrap/README.md @@ -215,9 +215,7 @@ This is executable, bounded groundwork rather than an untested placeholder. failure rollback for OpenClaw, Hermes, and LangChain Deep Agents Code through an MXC-named fake driver. `runtime-provider-contract.test.ts` verifies the production Docker registration and an MXC-style bootstrap surface through the -same provider bundle contract. `runtime-provider-source-shape.test.ts` -inventories the protocol, provider, and image-packaging surfaces and proves that -ordinary onboarding does not select managed bootstrap. +same provider bundle contract. The native entrypoint and composed managed-bootstrap image runtime are compiled and packaged in every managed agent image. Internal Docker qualification and From 2e2ec39d67c9cc523e9798efdc49dbb1b6fb2f94 Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 12:06:03 -0700 Subject: [PATCH 3/6] docs: clarify retained test evidence --- src/lib/inference/nvidia-featured-models.ts | 2 +- test/vitest-developer-feedback.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/inference/nvidia-featured-models.ts b/src/lib/inference/nvidia-featured-models.ts index 6c0b012014f..27b7fe1adec 100644 --- a/src/lib/inference/nvidia-featured-models.ts +++ b/src/lib/inference/nvidia-featured-models.ts @@ -11,7 +11,7 @@ export const NVIDIA_FEATURED_MODELS_URL = // NVIDIA Endpoints retirement contract: the public featured feed and // authenticated /models catalog can lag a runtime retirement. The repository // authority is CLOUD_MODEL_OPTIONS. nvidia-featured-models.test.ts verifies -// that the NVIDIA picker excludes retired entries, and config.test.ts verifies +// that the NVIDIA Endpoints picker excludes retired entries, and config.test.ts verifies // that Hermes Provider retains its independent model catalog. Keep entries // in this policy deny-list until a deliberate product change confirms that the // NVIDIA chat-completions route is available again or names a live successor. diff --git a/test/vitest-developer-feedback.test.ts b/test/vitest-developer-feedback.test.ts index ee8462d227e..2368462e680 100644 --- a/test/vitest-developer-feedback.test.ts +++ b/test/vitest-developer-feedback.test.ts @@ -10,7 +10,7 @@ import { runVitestNpmScript } from "./helpers/vitest-npm-script"; const focusedProjects = "--project cli --project plugin --project e2e-support"; describe("Vitest developer feedback", () => { - it("selects passed-only output for CI (#6692)", () => { + it("selects passed-only Vitest output in CI (#6692)", () => { expect(resolveVitestFeedback({})).toEqual({ isCi: false, silent: false }); expect(resolveVitestFeedback({ CI: "0" })).toEqual({ isCi: false, silent: false }); expect(resolveVitestFeedback({ CI: "1" })).toEqual({ isCi: true, silent: "passed-only" }); From 5299240cc6fb4b59a5ac6cbe1c78365b5963751e Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 12:18:38 -0700 Subject: [PATCH 4/6] test(security): restore MCP credential rejection coverage --- ci/source-shape-test-budget.json | 5 ++++ .../mcp-bridge-input-validation.test.ts | 29 +++++++++++++++++++ src/lib/inference/nvidia-featured-models.ts | 4 +-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 3c855635cbb..93590fae2e7 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -1,6 +1,11 @@ { "maxSourceShapeCases": 0, "sourceShapeContractExceptions": [ + { + "file": "src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts", + "test": "rejects every OpenShell child-visible credential key at each MCP boundary", + "category": "security" + }, { "file": "src/lib/readiness/host.test.ts", "test": "bounds and redacts successful probe text before schema validation", diff --git a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts index 49c6503e88b..b8b23b05331 100644 --- a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts +++ b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts @@ -119,6 +119,35 @@ describe("MCP CLI input validation", () => { } }); + // source-shape-contract: security -- Manifest-owned OpenShell child-visible keys must fail at every MCP credential attachment boundary + it("rejects every OpenShell child-visible credential key at each MCP boundary", () => { + const groups = [ + { + names: childVisibleCredentialManifest.rawChildValueKeys, + error: /materialized as a raw child-process value|preserve the host-only credential boundary/, + }, + { + names: childVisibleCredentialManifest.rewrittenChildValueKeys, + error: /rewritten by OpenShell's Google Cloud metadata compatibility path/, + }, + ]; + + for (const { names, error } of groups) { + for (const name of names) { + expect(() => + parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", "--env", name]), + ).toThrow(error); + expect(() => resolveCredentialEnv([{ name, value: "host-only-secret" }])).toThrow(error); + expect(() => + buildMcpBridgeProviderArgs("create", "provider", [{ name }], { + [name]: "host-only-secret", + }), + ).toThrow(error); + } + } + }); + + it("rejects sandbox runtime-control names as MCP credentials", () => { for (const name of [ "BASH_ENV", diff --git a/src/lib/inference/nvidia-featured-models.ts b/src/lib/inference/nvidia-featured-models.ts index 27b7fe1adec..580ef43ece8 100644 --- a/src/lib/inference/nvidia-featured-models.ts +++ b/src/lib/inference/nvidia-featured-models.ts @@ -11,8 +11,8 @@ export const NVIDIA_FEATURED_MODELS_URL = // NVIDIA Endpoints retirement contract: the public featured feed and // authenticated /models catalog can lag a runtime retirement. The repository // authority is CLOUD_MODEL_OPTIONS. nvidia-featured-models.test.ts verifies -// that the NVIDIA Endpoints picker excludes retired entries, and config.test.ts verifies -// that Hermes Provider retains its independent model catalog. Keep entries +// the featured-feed filter, and config.test.ts verifies that retired model IDs +// remain absent from NVIDIA Endpoints choices. Keep entries // in this policy deny-list until a deliberate product change confirms that the // NVIDIA chat-completions route is available again or names a live successor. const RETIRED_NVIDIA_FEATURED_MODEL_IDS = new Set([ From d85ac9f3a28ef30a79951e66dc916da2f59c931d Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 12:34:48 -0700 Subject: [PATCH 5/6] test(security): cover MCP environment argument forms --- ci/source-shape-test-budget.json | 5 -- .../mcp-bridge-input-validation.test.ts | 60 ++++++++++--------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 93590fae2e7..3c855635cbb 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -1,11 +1,6 @@ { "maxSourceShapeCases": 0, "sourceShapeContractExceptions": [ - { - "file": "src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts", - "test": "rejects every OpenShell child-visible credential key at each MCP boundary", - "category": "security" - }, { "file": "src/lib/readiness/host.test.ts", "test": "bounds and redacts successful probe text before schema validation", diff --git a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts index b8b23b05331..2d27577aad4 100644 --- a/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts +++ b/src/lib/actions/sandbox/mcp-bridge-input-validation.test.ts @@ -16,6 +16,24 @@ import { } from "./mcp-bridge"; import childVisibleCredentialManifest from "./openshell-child-visible-credentials.v0.0.101.json"; +const CHILD_VISIBLE_CREDENTIAL_CASES = [ + { + names: childVisibleCredentialManifest.rawChildValueKeys, + error: /materialized as a raw child-process value|preserve the host-only credential boundary/, + }, + { + names: childVisibleCredentialManifest.rewrittenChildValueKeys, + error: /rewritten by OpenShell's Google Cloud metadata compatibility path/, + }, +].flatMap(({ names, error }) => + names.flatMap((name) => [ + { name, form: "--env NAME", envArgs: ["--env", name], error }, + { name, form: "-e NAME", envArgs: ["-e", name], error }, + { name, form: "--env=NAME", envArgs: [`--env=${name}`], error }, + ]), +); + + describe("MCP CLI input validation", () => { it("parses server, URL, and env references", () => { const parsed = parseMcpAddArgs([ @@ -119,34 +137,20 @@ describe("MCP CLI input validation", () => { } }); - // source-shape-contract: security -- Manifest-owned OpenShell child-visible keys must fail at every MCP credential attachment boundary - it("rejects every OpenShell child-visible credential key at each MCP boundary", () => { - const groups = [ - { - names: childVisibleCredentialManifest.rawChildValueKeys, - error: /materialized as a raw child-process value|preserve the host-only credential boundary/, - }, - { - names: childVisibleCredentialManifest.rewrittenChildValueKeys, - error: /rewritten by OpenShell's Google Cloud metadata compatibility path/, - }, - ]; - - for (const { names, error } of groups) { - for (const name of names) { - expect(() => - parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", "--env", name]), - ).toThrow(error); - expect(() => resolveCredentialEnv([{ name, value: "host-only-secret" }])).toThrow(error); - expect(() => - buildMcpBridgeProviderArgs("create", "provider", [{ name }], { - [name]: "host-only-secret", - }), - ).toThrow(error); - } - } - }); - + it.each(CHILD_VISIBLE_CREDENTIAL_CASES)( + "rejects $name from $form at every MCP credential boundary", + ({ name, envArgs, error }) => { + expect(() => + parseMcpAddArgs(["github", "--url", "https://mcp.example.test/mcp", ...envArgs]), + ).toThrow(error); + expect(() => resolveCredentialEnv([{ name, value: "host-only-secret" }])).toThrow(error); + expect(() => + buildMcpBridgeProviderArgs("create", "provider", [{ name }], { + [name]: "host-only-secret", + }), + ).toThrow(error); + }, + ); it("rejects sandbox runtime-control names as MCP credentials", () => { for (const name of [ From 6edde419fe42f9565402df5d302f7325b88be2eb Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sun, 16 Aug 2026 12:40:07 -0700 Subject: [PATCH 6/6] test(security): preserve lifecycle policy reconciliation --- ci/source-shape-test-budget.json | 5 + test/openclaw-lifecycle-policy.test.ts | 166 +++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 test/openclaw-lifecycle-policy.test.ts diff --git a/ci/source-shape-test-budget.json b/ci/source-shape-test-budget.json index 3c855635cbb..a7bdd1d4a15 100644 --- a/ci/source-shape-test-budget.json +++ b/ci/source-shape-test-budget.json @@ -106,6 +106,11 @@ "test": "replaces the reviewed OpenClaw core tar and brace-expansion graph", "category": "security" }, + { + "file": "test/openclaw-lifecycle-policy.test.ts", + "test": "cross-checks the allowlist against every production archive install boundary", + "category": "security" + }, { "file": "test/openclaw-locked-install.test.ts", "test": "fails closed on missing required packages and symlinked package roots", diff --git a/test/openclaw-lifecycle-policy.test.ts b/test/openclaw-lifecycle-policy.test.ts new file mode 100644 index 00000000000..d63a4d1fbbd --- /dev/null +++ b/test/openclaw-lifecycle-policy.test.ts @@ -0,0 +1,166 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { spawnSync } from "node:child_process"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; +import policy from "../ci/reviewed-npm-lifecycle-allowlist.json"; +import { reviewedOpenClawPluginIntegrityByPackageSpec } from "../src/lib/messaging/applier/build/messaging-build-applier.mts"; + +const REPO_ROOT = path.join(import.meta.dirname, ".."); +const PRODUCTION_BOUNDARY_AUDIT = String.raw` +const fs = require("node:fs"); +function between(source, startMarker, endMarker) { + const start = source.indexOf(startMarker); + const end = source.indexOf(endMarker, start + startMarker.length); + return start >= 0 && end > start ? source.slice(start, end) : ""; +} + +function corePackageSpecs(block) { + return [...block.matchAll( + /if \[ "\$OPENCLAW_VERSION" = "([0-9]+(?:\.[0-9]+){2})" \]; then EXPECTED_INTEGRITY=/g, + )].map((match) => "openclaw@" + match[1]).sort(); +} + +function explicitLifecycleScripts(block) { + const scripts = [...block.matchAll( + /^\s*([0-9]+(?:\.[0-9]+){2}(?:\|[0-9]+(?:\.[0-9]+){2})*)\)\s+(node [^;]+postinstall-bundled-plugins\.mjs)\s+;;/gm, + )].flatMap((match) => + match[1].split("|").map((version) => ({ + packageSpec: "openclaw@" + version, + explicitCommand: match[2], + })), + ); + const lockedRuntimeCommand = + "node /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/openclaw/scripts/postinstall-bundled-plugins.mjs"; + if ( + block.includes("npm --prefix /usr/local/lib/nemoclaw/openclaw-runtime ci") && + block.includes(lockedRuntimeCommand) + ) { + const manifest = JSON.parse( + fs.readFileSync("agents/openclaw/openclaw-runtime/package.json", "utf8"), + ); + scripts.push({ + packageSpec: "openclaw@" + manifest.dependencies.openclaw, + explicitCommand: lockedRuntimeCommand, + }); + } + return scripts.sort((left, right) => left.packageSpec.localeCompare(right.packageSpec)); +} + +const dockerfile = fs.readFileSync("Dockerfile", "utf8"); +const dockerfileBase = fs.readFileSync("Dockerfile.base", "utf8"); +const messagingApplier = fs.readFileSync( + "src/lib/messaging/applier/build/messaging-build-applier.mts", + "utf8", +); + +const codexBlock = between( + dockerfile, + "AS codex-acp-runtime", + "AS wechat-npm-cache", +); +const runtimeBlock = between( + dockerfile, + "# Upgrade OpenClaw if the base image is stale.", + "# Patch OpenClaw media fetch for proxy-only sandbox", +); +const baseBlock = between( + dockerfileBase, + "# Install OpenClaw CLI + PyYAML.", + "# Baseline health check.", +); +const optionalPluginBlock = between( + dockerfile, + "# Install non-messaging OpenClaw plugins that need to match the runtime.", + "# Lock down npm for the next RUN", +); +const messagingInstallBlock = between( + messagingApplier, + "export function installOpenClawMessagingPlugins", + "export function runOpenClawMessagingDoctor", +); + +const codexMatch = dockerfile.match( + /ADD --checksum=sha256:[0-9a-f]{64} https:\/\/registry\.npmjs\.org\/@zed-industries\/codex-acp\/-\/codex-acp-0\.11\.1\.tgz/, +); +const optionalPluginSpecs = [...optionalPluginBlock.matchAll( + /"(@openclaw\/[^"\s]+@[0-9]+(?:\.[0-9]+){2})"\)\s+expected_integrity=/g, + )].map((match) => match[1]).sort(); + +console.log(JSON.stringify({ + codexPackageSpec: codexMatch ? "@zed-industries/codex-acp@0.11.1" : null, + runtimeCoreSpecs: corePackageSpecs(runtimeBlock), + baseCoreSpecs: corePackageSpecs(baseBlock), + optionalPluginSpecs, + runtimeLifecycleScripts: explicitLifecycleScripts(runtimeBlock), + baseLifecycleScripts: explicitLifecycleScripts(baseBlock), + scriptsSuppressed: { + codex: /npm install -g --offline --no-audit --no-fund --no-progress --ignore-scripts/.test(codexBlock), + runtime: /npm install -g --no-audit --no-fund --no-progress --ignore-scripts "\$OPENCLAW_PACK_PATH"/.test(runtimeBlock), + base: /npm install -g --ignore-scripts "\$OPENCLAW_PACK_PATH"/.test(baseBlock), + optionalPlugin: /NPM_CONFIG_IGNORE_SCRIPTS=true npm_config_ignore_scripts=true\s+\\\s*openclaw plugins install "npm-pack:/.test(optionalPluginBlock) && + optionalPluginBlock.includes('openclaw plugins install "npm-pack:\${plugin_install_archive}"'), + messagingPlugin: [ + '["openclaw", "plugins", "install", \`npm-pack:\${packed.archivePath}\`]', + 'NPM_CONFIG_IGNORE_SCRIPTS: "true"', + 'npm_config_ignore_scripts: "true"', + ].every((marker) => messagingInstallBlock.includes(marker)), + }, + legacyCoreRunsNoLifecycle: [runtimeBlock, baseBlock].every((block) => + /^\s*2026\.3\.11\)\s+;;/m.test(block), + ), + unknownCoreVersionFailsClosed: [runtimeBlock, baseBlock].every((block) => + /^\s*\*\).*no reviewed lifecycle policy.*exit 1/m.test(block), + ), +})); +`; + +describe("reviewed npm lifecycle policy", () => { + // source-shape-contract: security -- Every executable archive install must match the reviewed fail-closed lifecycle allowlist + it("cross-checks the allowlist against every production archive install boundary", () => { + expect(policy).toMatchObject({ schemaVersion: 1, defaultPolicy: "deny" }); + expect(policy.allowedLifecycleScripts).not.toHaveLength(0); + expect( + policy.allowedLifecycleScripts.every( + ({ event, manifestCommand }) => + event === "postinstall" && + manifestCommand === "node scripts/postinstall-bundled-plugins.mjs", + ), + ).toBe(true); + + const messagingPackageSpecs = Object.keys( + reviewedOpenClawPluginIntegrityByPackageSpec({ OPENCLAW_VERSION: "2026.7.1" }), + ); + const result = spawnSync(process.execPath, ["-e", PRODUCTION_BOUNDARY_AUDIT], { + cwd: REPO_ROOT, + encoding: "utf8", + }); + + expect(result.status, `${result.stdout}${result.stderr}`).toBe(0); + const audit = JSON.parse(result.stdout); + expect(audit.runtimeCoreSpecs).toEqual(audit.baseCoreSpecs); + expect( + [ + audit.codexPackageSpec, + ...audit.runtimeCoreSpecs, + ...audit.optionalPluginSpecs, + ...messagingPackageSpecs, + ].sort(), + ).toEqual([...policy.reviewedArchivePackages].sort()); + expect(audit.scriptsSuppressed).toEqual({ + codex: true, + runtime: true, + base: true, + optionalPlugin: true, + messagingPlugin: true, + }); + const allowedLifecycleScripts = policy.allowedLifecycleScripts + .map(({ packageSpec, explicitCommand }) => ({ packageSpec, explicitCommand })) + .sort((left, right) => left.packageSpec.localeCompare(right.packageSpec)); + expect(audit.runtimeLifecycleScripts).toEqual(audit.baseLifecycleScripts); + expect(audit.runtimeLifecycleScripts).toEqual(allowedLifecycleScripts); + expect(audit.legacyCoreRunsNoLifecycle).toBe(true); + expect(audit.unknownCoreVersionFailsClosed).toBe(true); + }); +});