#!/usr/bin/env python3 import hashlib import importlib.machinery import importlib.util import json import os import subprocess import tarfile import tempfile import unittest from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent PLATFORM_ROOT = SCRIPT_DIR.parent.parent ENGINE_ROOT = PLATFORM_ROOT.parent / "NODEDC_ENGINE_INFRA" RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy" BUILDER = SCRIPT_DIR / "build-engine-mcp-autonomy-provider-v5-artifact.mjs" PATCH_ID = "20991231-998" CANONICAL_ARTIFACT = ( PLATFORM_ROOT / "infra/deploy-artifacts/nodedc-engine-mcp-autonomy-provider-v5-20260720-004.tgz" ) CANONICAL_SHA256 = "3400954cdce078892a06b04b9bfd85a90f6ea775b1a0caf99eba1f880ef6601c" def load_runner(): loader = importlib.machinery.SourceFileLoader( "nodedc_engine_mcp_autonomy_provider_v5", str(RUNNER_PATH), ) spec = importlib.util.spec_from_loader(loader.name, loader) module = importlib.util.module_from_spec(spec) loader.exec_module(module) return module RUNNER = load_runner() class EngineMcpAutonomyProviderV5Test(unittest.TestCase): def build(self, artifact_dir): environment = os.environ.copy() environment["NODEDC_ENGINE_SOURCE_ROOT"] = str(ENGINE_ROOT) environment["NODEDC_DEPLOY_ARTIFACT_DIR"] = str(artifact_dir) completed = subprocess.run( ["node", str(BUILDER), PATCH_ID], cwd=PLATFORM_ROOT, env=environment, check=True, capture_output=True, text=True, ) return json.loads(completed.stdout) def test_canonical_artifact_digest_and_members_are_pinned(self): self.assertEqual( hashlib.sha256(CANONICAL_ARTIFACT.read_bytes()).hexdigest(), CANONICAL_SHA256, ) self.assertEqual(CANONICAL_ARTIFACT.read_bytes()[4:8], b"\0\0\0\0") with tarfile.open(CANONICAL_ARTIFACT, "r:gz") as archive: for member in archive: self.assertTrue(member.isfile() or member.isdir()) self.assertFalse(Path(member.name).name.startswith("._")) def test_builder_is_reproducible_and_slice_is_backend_only(self): with tempfile.TemporaryDirectory(prefix="nodedc-engine-mcp-autonomy-v5-") as directory: root = Path(directory) first = self.build(root / "first") second = self.build(root / "second") first_artifact = Path(first["artifact"]) second_artifact = Path(second["artifact"]) self.assertEqual(first_artifact.read_bytes(), second_artifact.read_bytes()) self.assertEqual( first["artifactSha256"], hashlib.sha256(first_artifact.read_bytes()).hexdigest(), ) self.assertEqual(first["services"], ["nodedc-backend"]) self.assertEqual( first["authority"], "mcp-capability-intersect-user-objective", ) extract = root / "extract" with tarfile.open(first_artifact, "r:gz") as archive: archive.extractall(extract, filter="data") loaded = root / "loaded" loaded.mkdir() manifest, entries, payload = RUNNER.load_artifact(first_artifact, loaded) descriptor = RUNNER.validate_engine_mcp_autonomy_provider_v5_payload( payload, entries, ) self.assertEqual(manifest["component"], "engine") self.assertEqual( tuple(entries), RUNNER.ENGINE_MCP_AUTONOMY_PROVIDER_V5_ARTIFACT_ENTRIES, ) self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",)) self.assertEqual(RUNNER.component_builds("engine", entries), ()) self.assertEqual( descriptor["source"]["gatewaySha256"], RUNNER.ENGINE_MCP_AUTONOMY_PROVIDER_V5_TARGET_SHA256[ RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL ], ) def test_payload_pins_authority_policy_archive_and_catalog_lineage(self): with tempfile.TemporaryDirectory(prefix="nodedc-engine-mcp-autonomy-v5-policy-") as directory: result = self.build(Path(directory) / "artifact") extract = Path(directory) / "extract" with tarfile.open(result["artifact"], "r:gz") as archive: archive.extractall(extract, filter="data") payload = extract / "payload" installer = ( payload / "nodedc-source/server/assets/engine-agent-npm/bin/nodedc-engine-codex-agent.mjs" ).read_text(encoding="utf-8") catalog = json.loads(( payload / "nodedc-source/server/assets/provider-packages/v1/catalog.json" ).read_text(encoding="utf-8")) self.assertIn("MCP tool availability establishes capability authority", installer) self.assertIn("machine safety barrier, not a permission ceremony", installer) self.assertIn("Three identical failures with no new evidence", installer) self.assertNotIn("only with explicit user confirmation", installer) self.assertEqual( [item["id"] for item in catalog["packages"]], ["gelios.provider.v4", "gelios.provider.v5"], ) self.assertTrue(all( capability["dataProductIds"] == ["fleet.positions.current.v4"] for package in catalog["packages"] if package["id"] == "gelios.provider.v5" for capability in package["capabilities"] )) def test_payload_tampering_is_rejected(self): with tempfile.TemporaryDirectory(prefix="nodedc-engine-mcp-autonomy-v5-tamper-") as directory: result = self.build(Path(directory) / "artifact") extract = Path(directory) / "extract" RUNNER.safe_extract(Path(result["artifact"]), extract) entries = RUNNER.parse_files_list(extract / "files.txt") package = extract / "payload/nodedc-source/server/assets/engine-agent-npm/package.json" package.write_text("{}\n", encoding="utf-8") with self.assertRaisesRegex(RUNNER.DeployError, "target sha256 mismatch"): RUNNER.validate_engine_mcp_autonomy_provider_v5_payload( extract / "payload", entries, ) if __name__ == "__main__": unittest.main(verbosity=2)