feat(engine): register MCP profiles and provider transitions

This commit is contained in:
Codex
2026-07-25 15:39:23 +03:00
parent 951b884c4b
commit e9e03143cd
21 changed files with 3573 additions and 28 deletions
@@ -0,0 +1,276 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import {
copyFile,
lstat,
mkdir,
mkdtemp,
readFile,
rm,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(scriptDir, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT
|| join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactDir = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR
|| resolve(scriptDir, "../deploy-artifacts"),
);
const [patchId = "engine-l1-agent-init-concurrency-20260724-042", ...extra] =
process.argv.slice(2);
if (
extra.length
|| !/^engine-l1-agent-init-concurrency-\d{8}-\d{3}$/.test(patchId)
) {
throw new Error(
"usage: build-engine-l1-agent-init-concurrency-artifact.mjs "
+ "[engine-l1-agent-init-concurrency-YYYYMMDD-NNN]",
);
}
const sourceCommit = "c4077fe0d8d824fa58616eeb986dc78ca43070da";
const predecessorSha256 = Object.freeze({
"nodedc-source/src/App.tsx":
"b3e61a89330b774f309660208d05143d299ab582f18765c1c14e2122a62c4d5e",
"nodedc-source/src/driveinspector/nodes/N8n.definition.ts":
"a4890cca12b269643ec3255c2fc6b7e2be96aa042ffc6087772e63cbf8323c3a",
"nodedc-source/src/nodes/N8nNode.tsx":
"a125f7cde66085008dafe5a340a1143094c59769573815851ce6c8adfe4c0220",
"nodedc-source/src/store.ts":
"2128cd582a947582bb7736792c3a71551712262ef04882c189220ec79f16fb8e",
"nodedc-source/dist/index.html":
"90d72f8790dc8cf951066b1210447c84d640373117bae23f3a4cb3227fb96d6d",
"nodedc-source/dist/assets/index-CqvJfRRS.js":
"06e6c23b03ea2ba8a4890e1f1714fd08ebaf18d735834200af6ab430af360ca8",
});
const targetSha256 = Object.freeze({
"nodedc-source/src/App.tsx":
"fc580dc3a1a97393af81dd75c54ae8b37db1f6fda8364042198493493b15f2c2",
"nodedc-source/src/driveinspector/nodes/N8n.definition.ts":
"945839541547b2fd02b5424954e00483d6c76f82a333d6a7a652ccd1b74d04cf",
"nodedc-source/src/nodes/N8nNode.tsx":
"1130e355d86e06a18df775b2d3517bfdbf98fdc494ca707d23c78648fbfd3cb4",
"nodedc-source/src/store.ts":
"46884488254c16cd3af9b25556dd0db4f5a3a20047abdb496db831f204e40673",
"nodedc-source/src/utils/workflowWriteQueue.js":
"41f73ccb5e1dafbdae501b7c0b9fa5c47fdbd52564061b9c4ca6ca1c75ceccdf",
"nodedc-source/dist/index.html":
"1554e2418aead13b56328c5721dd677400d84ee087559a88fe60b295b7ff5412",
"nodedc-source/dist/assets/index-r1_2ECzJ.js":
"0d25dd843da7078b8dbad5cb4b78724bf1ca8aa067e9d0add1e09ce8f421b822",
});
const entries = Object.freeze(Object.keys(targetSha256));
const artifact = join(artifactDir, `nodedc-${patchId}.tgz`);
const checksum = `${artifact}.sha256`;
assertSourceCommit();
await assertPredecessorSources();
await assertExactTargets();
await assertRuntimeContract();
await assertFresh(artifact);
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-l1-agent-init-"));
try {
for (const relativePath of entries) {
const destination = join(stage, "payload", relativePath);
await mkdir(dirname(destination), { recursive: true });
await copyFile(join(engineRoot, relativePath), destination);
}
await writeFile(
join(stage, "manifest.env"),
`id=${patchId}\ncomponent=engine\ntype=app-overlay\n`,
{ encoding: "utf8", flag: "wx", mode: 0o644 },
);
await writeFile(join(stage, "files.txt"), `${entries.join("\n")}\n`, {
encoding: "utf8",
flag: "wx",
mode: 0o644,
});
await mkdir(artifactDir, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
const sha256 = digest(await readFile(artifact));
await writeFile(checksum, `${sha256} ${artifact.split("/").at(-1)}\n`, {
encoding: "utf8",
flag: "wx",
mode: 0o644,
});
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
checksum,
sha256,
sourceCommit,
predecessorSha256,
targetSha256,
entries,
services: ["nodedc-backend", "app"],
healthchecks: [
"http://127.0.0.1:8080/",
"http://127.0.0.1:3001/health",
],
concurrencyContract: "per-workflow-fifo-latest-revision-v1",
n8nCoreChanged: false,
untouched: [
"n8n runtime",
"L1 workflow data",
"L2 workflow data",
"credentials",
"databases",
"MCP catalogs",
],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
function assertSourceCommit() {
const actual = run("git", ["-C", engineRoot, "rev-parse", "HEAD"]).stdout.trim();
if (actual !== sourceCommit) {
throw new Error(
`engine_l1_agent_init_source_commit_mismatch:`
+ `expected=${sourceCommit}:actual=${actual}`,
);
}
}
async function assertPredecessorSources() {
for (const [relativePath, expected] of Object.entries(predecessorSha256)) {
const result = run("git", [
"-C",
engineRoot,
"show",
`${sourceCommit}:${relativePath}`,
]);
const actual = digest(result.stdoutBuffer);
if (actual !== expected) {
throw new Error(
`engine_l1_agent_init_predecessor_mismatch:${relativePath}:`
+ `expected=${expected}:actual=${actual}`,
);
}
}
const newFile = "nodedc-source/src/utils/workflowWriteQueue.js";
const probe = spawnSync(
"git",
["-C", engineRoot, "cat-file", "-e", `${sourceCommit}:${newFile}`],
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] },
);
if (probe.status === 0) {
throw new Error("engine_l1_agent_init_queue_not_new");
}
}
async function assertExactTargets() {
for (const [relativePath, expected] of Object.entries(targetSha256)) {
const source = join(engineRoot, relativePath);
const info = await lstat(source);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_l1_agent_init_source_unsafe:${relativePath}`);
}
const actual = digest(await readFile(source));
if (actual !== expected) {
throw new Error(
`engine_l1_agent_init_target_mismatch:${relativePath}:`
+ `expected=${expected}:actual=${actual}`,
);
}
}
}
async function assertRuntimeContract() {
const app = await readFile(join(engineRoot, "nodedc-source/src/App.tsx"), "utf8");
const definition = await readFile(
join(engineRoot, "nodedc-source/src/driveinspector/nodes/N8n.definition.ts"),
"utf8",
);
const store = await readFile(join(engineRoot, "nodedc-source/src/store.ts"), "utf8");
const node = await readFile(
join(engineRoot, "nodedc-source/src/nodes/N8nNode.tsx"),
"utf8",
);
const queue = await readFile(
join(engineRoot, "nodedc-source/src/utils/workflowWriteQueue.js"),
"utf8",
);
const index = await readFile(
join(engineRoot, "nodedc-source/dist/index.html"),
"utf8",
);
if (
!app.includes("createWorkflowWriteQueue")
|| !app.includes("putExistingWorkflow")
|| !app.includes("expectedRevision: currentWorkflowRevisionRef.current")
|| !queue.includes("previous.catch(() => undefined).then(() => operation())")
|| !definition.includes("nodeName: 'NDC'")
|| !definition.includes("default: 'NDC'")
|| !definition.includes("data?.title || data?.nodeName || 'NDC'")
|| !store.includes("nodeName: 'NDC'")
|| !node.includes("data?.nodeName ?? 'NDC'")
|| !index.includes("/assets/index-r1_2ECzJ.js")
|| /gelios|robot2b/i.test(queue)
) {
throw new Error("engine_l1_agent_init_runtime_contract_invalid");
}
}
async function assertFresh(path) {
try {
await lstat(path);
} catch (error) {
if (error?.code === "ENOENT") return;
throw error;
}
throw new Error("artifact_already_exists");
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'xb') as out:",
" with gzip.GzipFile(filename='',mode='wb',fileobj=out,compresslevel=9,mtime=0) as gz:",
" with tarfile.open(fileobj=gz,mode='w',format=tarfile.PAX_FORMAT) as tar:",
" for top in ('manifest.env','files.txt','payload'):",
" p=root/top; paths=[p]+(sorted(p.rglob('*')) if p.is_dir() else [])",
" for x in paths:",
" info=tar.gettarinfo(str(x),arcname=x.relative_to(root).as_posix())",
" info.uid=info.gid=0; info.uname=info.gname='root'; info.mtime=0; info.mode=0o755 if info.isdir() else 0o644",
" with (open(x,'rb') if info.isfile() else io.BytesIO()) as src: tar.addfile(info,src if info.isfile() else None)",
].join("\n");
}
function digest(value) {
return createHash("sha256").update(value).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: null,
stdio: ["ignore", "pipe", "pipe"],
maxBuffer: 128 * 1024 * 1024,
});
if (result.status !== 0) {
throw new Error(
`${command}_failed:${Buffer.from(result.stderr || "").toString("utf8")}`
+ `${Buffer.from(result.stdout || "").toString("utf8")}`,
);
}
return {
stdoutBuffer: Buffer.from(result.stdout || ""),
stderrBuffer: Buffer.from(result.stderr || ""),
stdout: Buffer.from(result.stdout || "").toString("utf8"),
stderr: Buffer.from(result.stderr || "").toString("utf8"),
};
}
@@ -0,0 +1,230 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import {
copyFile,
lstat,
mkdir,
mkdtemp,
readFile,
rm,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(scriptDir, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT
|| join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactDir = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR
|| resolve(scriptDir, "../deploy-artifacts"),
);
const [
patchId = "engine-mcp-gelios-units-items-envelope-20260724-049",
...extra
] = process.argv.slice(2);
if (
extra.length
|| !/^engine-mcp-gelios-units-items-envelope-\d{8}-\d{3}$/.test(patchId)
) {
throw new Error(
"usage: build-engine-mcp-gelios-units-items-envelope-artifact.mjs "
+ "[engine-mcp-gelios-units-items-envelope-YYYYMMDD-NNN]",
);
}
const expectedSha256 = Object.freeze({
"nodedc-source/server/assets/execution-plans/v1/catalog.json":
"d0cc95fa5e55bda315947fdb13bd8a0d8931b9484677e4c4cc0dcb0e9614e215",
"nodedc-source/server/assets/provider-packages/v1/catalog.json":
"1f1b866b6f837bffc6d529dfffd8bfa9c87495bfcd9ae3515a79765143d94b1d",
"nodedc-source/server/deployTransitions/geliosUnitsItemsEnvelopeV12Patch1.json":
"7a1594573e98342d3a3edcc0dc4f663f06b30ca24cc20adb5f36d50591066d96",
});
const files = Object.freeze(Object.keys(expectedSha256));
const artifact = join(artifactDir, `nodedc-${patchId}.tgz`);
const checksum = `${artifact}.sha256`;
const stage = await mkdtemp(
join(tmpdir(), "nodedc-engine-gelios-units-items-envelope-"),
);
await assertFresh(artifact);
await assertExactSources();
try {
for (const relativePath of files) {
const destination = join(stage, "payload", relativePath);
await mkdir(dirname(destination), { recursive: true });
await copyFile(join(engineRoot, relativePath), destination);
}
await writeFile(
join(stage, "manifest.env"),
`id=${patchId}\ncomponent=engine\ntype=app-overlay\n`,
"utf8",
);
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactDir, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
const sha256 = digest(await readFile(artifact));
await writeFile(
checksum,
`${sha256} ${artifact.split("/").at(-1)}\n`,
"utf8",
);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
checksum,
sha256,
services: ["nodedc-backend"],
transition:
"registered-profiles-v2-to-gelios-v12.0.1-units-items-envelope",
mcpVersion: "0.12.0",
providerPackage: {
id: "gelios.provider.v12",
predecessorVersion: "12.0.0",
targetVersion: "12.0.1",
},
registeredProfile: "gelios.units.profile.cold.v1",
responseCollectionPath: "items",
existingMaterializerReused: true,
compilerVersion: "1.4.0",
engineRuntimeCodeChanged: false,
n8nCoreChanged: false,
l1Changed: false,
l2GraphChanged: false,
engineUiChanged: false,
databasesChanged: false,
credentialsChanged: false,
foundryChanged: false,
ontologyChanged: false,
providerEndpointsChanged: false,
files,
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(expectedSha256)) {
const sourcePath = join(engineRoot, relativePath);
const info = await lstat(sourcePath);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(
`engine_gelios_units_items_source_unsafe:${relativePath}`,
);
}
const actual = digest(await readFile(sourcePath));
if (actual !== expected) {
throw new Error(
`engine_gelios_units_items_target_mismatch:${relativePath}:`
+ `expected=${expected}:actual=${actual}`,
);
}
}
const execution = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/server/assets/execution-plans/v1/catalog.json",
),
"utf8",
));
const security = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/server/assets/provider-packages/v1/catalog.json",
),
"utf8",
));
const descriptor = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/server/deployTransitions/"
+ "geliosUnitsItemsEnvelopeV12Patch1.json",
),
"utf8",
));
const providerPackage = execution.packages.find(
(item) => item.id === "gelios.provider.v12",
);
const profile = providerPackage?.profiles.find(
(item) => item.id === "gelios.units.profile.cold.v1",
);
const extract = profile?.executionPlanTemplate?.steps.find(
(step) => (
step.kind === "extract_items"
&& step.config?.capabilityId === "gelios.units.current.read"
),
);
const securityPackage = security.packages.find(
(item) => item.id === "gelios.provider.v12",
);
if (
providerPackage?.version !== "12.0.1"
|| securityPackage?.version !== "12.0.1"
|| profile?.dataProductId !== "fleet.units.profile.current.v1"
|| profile?.executionPlanTemplate?.compilerVersion !== "1.4.0"
|| extract?.config?.response?.collectionPaths?.[0] !== "items"
|| descriptor?.id
!== "engine-mcp-gelios-units-items-envelope-v12-patch1"
|| descriptor?.predecessor
!== "engine-mcp-registered-execution-profiles-v2"
|| descriptor?.mcpVersion !== "0.12.0"
|| descriptor?.registeredProfile?.materializer
!== "existing-immutable-two-phase"
|| Object.values(descriptor?.boundaries || {}).some(Boolean)
) {
throw new Error("engine_gelios_units_items_boundary_invalid");
}
}
async function assertFresh(path) {
try {
await lstat(path);
} catch (error) {
if (error?.code === "ENOENT") return;
throw error;
}
throw new Error("artifact_already_exists");
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'xb') as out:",
" with gzip.GzipFile(filename='',mode='wb',fileobj=out,compresslevel=9,mtime=0) as gz:",
" with tarfile.open(fileobj=gz,mode='w',format=tarfile.PAX_FORMAT) as tar:",
" for top in ('manifest.env','files.txt','payload'):",
" p=root/top; paths=[p]+(sorted(p.rglob('*')) if p.is_dir() else [])",
" for x in paths:",
" info=tar.gettarinfo(str(x),arcname=x.relative_to(root).as_posix())",
" info.uid=info.gid=0; info.uname=info.gname='root'; info.mtime=0; "
+ "info.mode=0o755 if info.isdir() else 0o644",
" with (open(x,'rb') if info.isfile() else io.BytesIO()) as src: "
+ "tar.addfile(info,src if info.isfile() else None)",
].join("\n");
}
function digest(value) {
return createHash("sha256").update(value).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -0,0 +1,279 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import {
copyFile,
lstat,
mkdir,
mkdtemp,
readFile,
rm,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(scriptDir, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT
|| join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactDir = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR
|| resolve(scriptDir, "../deploy-artifacts"),
);
const [
patchId = "engine-mcp-registered-execution-profiles-20260724-048",
...extra
] = process.argv.slice(2);
if (
extra.length
|| !/^engine-mcp-registered-execution-profiles-\d{8}-\d{3}$/.test(patchId)
) {
throw new Error(
"usage: build-engine-mcp-registered-execution-profiles-artifact.mjs "
+ "[engine-mcp-registered-execution-profiles-YYYYMMDD-NNN]",
);
}
const expectedSha256 = Object.freeze({
"nodedc-source/server/assets/execution-plans/v1/catalog.json":
"940510499a9260dbff718b7b1f96f72f8e9ac593b460805af3007731578a7668",
"nodedc-source/server/l2ExecutionPlan/catalog.js":
"fec56b154ae483ad21bbaaeb4c55707bffce223c27874ac135ce58a9203259a0",
"nodedc-source/server/l2ExecutionPlan/registeredProfiles.js":
"3c521c1652c61c9d757197c76e053fd3ec602e13ef7f6a4856835ecc1a8a61d1",
"nodedc-source/server/routes/engineAgentGateway.js":
"8f04edc11251de86b825351c92338be9537207887cf802474b6b6d8c3cce4077",
"nodedc-source/services/node-intelligence/activation.json":
"3d72709e40b79c01a62a6af4bde911fca4f609d5ac487d284cf97fd8ebd73686",
"nodedc-source/server/deployTransitions/registeredExecutionProfilesV2.json":
"1db523f035a47c6b00b41b26efe1390ad2d24acece9d30dd039eff56626e934d",
});
const files = Object.freeze(Object.keys(expectedSha256));
const artifact = join(artifactDir, `nodedc-${patchId}.tgz`);
const checksum = `${artifact}.sha256`;
const stage = await mkdtemp(
join(tmpdir(), "nodedc-engine-registered-execution-profiles-"),
);
await assertFresh(artifact);
await assertExactSources();
try {
for (const relativePath of files) {
const destination = join(stage, "payload", relativePath);
await mkdir(dirname(destination), { recursive: true });
await copyFile(join(engineRoot, relativePath), destination);
}
await writeFile(
join(stage, "manifest.env"),
`id=${patchId}\ncomponent=engine\ntype=app-overlay\n`,
"utf8",
);
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactDir, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
const sha256 = digest(await readFile(artifact));
await writeFile(
checksum,
`${sha256} ${artifact.split("/").at(-1)}\n`,
"utf8",
);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
checksum,
sha256,
services: ["nodedc-backend"],
mcpVersion: "0.12.0",
transition:
"gelios-items-envelope-v12-to-registered-profiles-v2-attested",
tools: [
"engine_list_l2_execution_profiles",
"engine_plan_registered_l2_execution",
],
registeredProfiles: 6,
existingMaterializerReused: true,
n8nCoreChanged: false,
l1Changed: false,
l2GraphChanged: false,
engineUiChanged: false,
databasesChanged: false,
credentialsChanged: false,
foundryChanged: false,
ontologyChanged: false,
nodeIntelligenceAttestationChanged: true,
nodeIntelligenceImageChanged: false,
nodeIntelligenceSourceChanged: false,
rawProviderValuesIncluded: false,
files,
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(expectedSha256)) {
const sourcePath = join(engineRoot, relativePath);
const info = await lstat(sourcePath);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(
`engine_registered_execution_profiles_source_unsafe:${relativePath}`,
);
}
const actual = digest(await readFile(sourcePath));
if (actual !== expected) {
throw new Error(
`engine_registered_execution_profiles_target_mismatch:${relativePath}:`
+ `expected=${expected}:actual=${actual}`,
);
}
}
const catalog = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/server/assets/execution-plans/v1/catalog.json",
),
"utf8",
));
const descriptor = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/server/deployTransitions/"
+ "registeredExecutionProfilesV2.json",
),
"utf8",
));
const registered = catalog.packages.flatMap(
(providerPackage) => (providerPackage.profiles || []).filter(
(profile) => profile.executionPlanTemplate,
),
);
if (
registered.length !== 6
|| registered.some((profile) => (
!profile.dataClass
|| !profile.cadence
|| profile.executionPlanTemplate?.compilerVersion !== "1.4.0"
|| profile.executionPlanTemplate?.connection?.collectionProfileId
!== profile.id
))
|| descriptor?.id !== "engine-mcp-registered-execution-profiles-v2"
|| descriptor?.predecessor !== "engine-mcp-gelios-items-envelope-v12"
|| descriptor?.mcpVersion !== "0.12.0"
|| descriptor?.tools?.apply
!== "engine_apply_l2_execution_plan_materialization"
|| descriptor?.nodeIntelligenceAttestation?.targetGatewaySha256
!== expectedSha256[
"nodedc-source/server/routes/engineAgentGateway.js"
]
|| descriptor?.nodeIntelligenceAttestation?.sidecarImageChanged !== false
|| descriptor?.nodeIntelligenceAttestation
?.nodeIntelligenceSourceChanged !== false
|| descriptor?.boundaries?.nodeIntelligenceAttestationChanged !== true
|| Object.entries(descriptor?.boundaries || {}).some(
([key, value]) => (
key !== "nodeIntelligenceAttestationChanged" && value !== false
),
)
) {
throw new Error("engine_registered_execution_profiles_boundary_invalid");
}
const gateway = await readFile(
join(engineRoot, "nodedc-source/server/routes/engineAgentGateway.js"),
"utf8",
);
const resolver = await readFile(
join(
engineRoot,
"nodedc-source/server/l2ExecutionPlan/registeredProfiles.js",
),
"utf8",
);
const nodeIntelligence = JSON.parse(await readFile(
join(
engineRoot,
"nodedc-source/services/node-intelligence/activation.json",
),
"utf8",
));
if (
nodeIntelligence?.releaseId !== "2.33.2-974a9fb3492f"
|| nodeIntelligence?.source?.gatewaySha256
!== expectedSha256[
"nodedc-source/server/routes/engineAgentGateway.js"
]
) {
throw new Error(
"engine_registered_execution_profiles_attestation_invalid",
);
}
for (const marker of [
"engine_list_l2_execution_profiles",
"engine_plan_registered_l2_execution",
"const ENGINE_AGENT_MCP_VERSION = '0.12.0'",
]) {
if (!gateway.includes(marker)) {
throw new Error(
`engine_registered_execution_profiles_gateway_marker_missing:${marker}`,
);
}
}
if (
!resolver.includes("registered_execution_profile_ref_scope_denied")
|| !resolver.includes("targetBoundPlan")
|| /gelios|robot2b/i.test(resolver)
) {
throw new Error("engine_registered_execution_profiles_resolver_invalid");
}
}
async function assertFresh(path) {
try {
await lstat(path);
} catch (error) {
if (error?.code === "ENOENT") return;
throw error;
}
throw new Error("artifact_already_exists");
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'xb') as out:",
" with gzip.GzipFile(filename='',mode='wb',fileobj=out,compresslevel=9,mtime=0) as gz:",
" with tarfile.open(fileobj=gz,mode='w',format=tarfile.PAX_FORMAT) as tar:",
" for top in ('manifest.env','files.txt','payload'):",
" p=root/top; paths=[p]+(sorted(p.rglob('*')) if p.is_dir() else [])",
" for x in paths:",
" info=tar.gettarinfo(str(x),arcname=x.relative_to(root).as_posix())",
" info.uid=info.gid=0; info.uname=info.gname='root'; info.mtime=0; "
+ "info.mode=0o755 if info.isdir() else 0o644",
" with (open(x,'rb') if info.isfile() else io.BytesIO()) as src: "
+ "tar.addfile(info,src if info.isfile() else None)",
].join("\n");
}
function digest(value) {
return createHash("sha256").update(value).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -12,6 +12,33 @@ import {
geliosTelemetryFieldRegistryV5,
} from "../../packages/external-provider-contract/providers/gelios/v12/index.mjs";
const PUBLIC_PROFILE_METADATA = Object.freeze({
"gelios.positions.current.realtime.v7": {
cadence: "hot",
dataClass: "operational",
},
"gelios.positions.current.manual.v7": {
cadence: "on_demand",
dataClass: "operational",
},
"gelios.geozones.current.realtime.v1": {
cadence: "cold",
dataClass: "operational",
},
"gelios.units.profile.cold.v1": {
cadence: "cold",
dataClass: "operational",
},
"gelios.units.contacts.cold.v1": {
cadence: "cold",
dataClass: "restricted",
},
"gelios.units.identity.warm.v1": {
cadence: "warm",
dataClass: "restricted",
},
});
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || "../NODEDC_ENGINE_INFRA",
);
@@ -72,9 +99,14 @@ function executionCatalogEntry() {
: {},
);
const { packageDigest: _packageDigest, ...artifacts } = plan.artifacts;
const publicMetadata = PUBLIC_PROFILE_METADATA[profile.id];
if (!publicMetadata) {
throw new Error(`gelios_v12_public_profile_metadata_missing:${profile.id}`);
}
return {
id: profile.id,
dataProductId: profile.dataProductId,
...publicMetadata,
capabilityIds: [...profile.capabilityIds],
stepSignatures: plan.steps.map((step) => ({
id: step.id,
@@ -87,6 +119,7 @@ function executionCatalogEntry() {
...(step.config.nodeType ? { nodeType: step.config.nodeType } : {}),
})),
artifacts,
executionPlanTemplate: plan,
};
});
return {
@@ -0,0 +1,195 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import { resolve } from "node:path";
import {
compileL2ExecutionPlan,
instantiateL2Connection,
} from "../../packages/external-provider-contract/src/index.mjs";
import {
GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
geliosProviderPackageV13,
} from "../../packages/external-provider-contract/providers/gelios/v13/index.mjs";
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || "../NODEDC_ENGINE_INFRA",
);
const executionCatalogPath = resolve(
engineRoot,
"nodedc-source/server/assets/execution-plans/v1/catalog.json",
);
const securityCatalogPath = resolve(
engineRoot,
"nodedc-source/server/assets/provider-packages/v1/catalog.json",
);
const executionCatalog = JSON.parse(
await readFile(executionCatalogPath, "utf8"),
);
for (const value of ["1.5.0"]) {
if (!executionCatalog.runtime.compilerVersions.includes(value)) {
executionCatalog.runtime.compilerVersions.push(value);
}
}
for (const value of ["bounded_response_lookup"]) {
if (!executionCatalog.runtime.derivationKinds.includes(value)) {
executionCatalog.runtime.derivationKinds.push(value);
}
}
for (const value of ["response.lookup.first", "response.lookup.list"]) {
if (!executionCatalog.runtime.ruleIds.includes(value)) {
executionCatalog.runtime.ruleIds.push(value);
}
}
executionCatalog.runtime.compilerVersions.sort();
executionCatalog.runtime.derivationKinds.sort();
executionCatalog.runtime.ruleIds.sort();
executionCatalog.packages = executionCatalog.packages.filter(
(providerPackage) => providerPackage.id !== geliosProviderPackageV13.id,
);
executionCatalog.packages.push(executionCatalogEntry());
await writeFile(executionCatalogPath, `${JSON.stringify(executionCatalog, null, 2)}\n`);
const securityCatalog = JSON.parse(
await readFile(securityCatalogPath, "utf8"),
);
securityCatalog.packages = securityCatalog.packages.filter(
(providerPackage) => providerPackage.id !== geliosProviderPackageV13.id,
);
securityCatalog.packages.push(securityCatalogEntry());
await writeFile(securityCatalogPath, `${JSON.stringify(securityCatalog, null, 2)}\n`);
console.log(JSON.stringify({
ok: true,
providerPackage: geliosProviderPackageV13.id,
executionCatalogPath,
securityCatalogPath,
historicalExecutionPackagePreserved: executionCatalog.packages.some(
(providerPackage) => providerPackage.id === "gelios.provider.v12",
),
historicalSecurityAuthorityPreserved: securityCatalog.packages.some(
(providerPackage) => providerPackage.id === "gelios.provider.v12",
),
activeContactsAuthority: geliosProviderPackageV13.id,
}, null, 2));
function selectedProfiles() {
return geliosProviderPackageV13.collectionProfiles.filter(
(profile) => profile.dataProductId === GELIOS_UNIT_CONTACTS_DATA_PRODUCT_ID,
);
}
function selectedCapabilityIds() {
return new Set(selectedProfiles().flatMap((profile) => profile.capabilityIds));
}
function executionCatalogEntry() {
const profiles = selectedProfiles().map((profile) => {
const connection = instantiateL2Connection(geliosProviderPackageV13, {
tenantId: "tenant-catalog-build",
connectionId: `catalog-${profile.id.replaceAll(".", "-")}`,
collectionProfileId: profile.id,
providerCredentialRef: "ndc-credref:catalog-build-provider-v13",
});
const plan = compileL2ExecutionPlan(geliosProviderPackageV13, connection);
const { packageDigest: _packageDigest, ...artifacts } = plan.artifacts;
return {
id: profile.id,
dataProductId: profile.dataProductId,
capabilityIds: [...profile.capabilityIds],
stepSignatures: plan.steps.map((step) => ({
id: step.id,
kind: step.kind,
...(step.config.capabilityId ? { capabilityId: step.config.capabilityId } : {}),
...(step.config.mappingContractId ? {
mappingContractId: step.config.mappingContractId,
} : {}),
...(step.config.dataProductId ? { dataProductId: step.config.dataProductId } : {}),
...(step.config.nodeType ? { nodeType: step.config.nodeType } : {}),
})),
artifacts,
};
});
const capabilityIds = selectedCapabilityIds();
return {
id: geliosProviderPackageV13.id,
providerId: geliosProviderPackageV13.providerId,
version: geliosProviderPackageV13.version,
contractDigest: canonicalDigest(geliosProviderPackageV13),
providerCredential: {
authModeId: "gelios.rest-rotating-bearer.v3",
credentialType: "ndcProviderRotatingAccessApi",
},
publisher: {
nodeType: "n8n-nodes-ndc.ndcDataProductPublish",
credentialType: "ndcDataProductWriterApi",
},
capabilities: geliosProviderPackageV13.capabilities
.filter((capability) => capabilityIds.has(capability.id))
.map((capability) => ({
id: capability.id,
contractDigest: canonicalDigest(capability),
requestDigest: canonicalDigest(capability.request),
method: capability.request.method,
url: requestUrl(capability.request),
})),
profiles,
};
}
function securityCatalogEntry() {
const productsByCapability = new Map(
geliosProviderPackageV13.capabilities.map((capability) => [capability.id, new Set()]),
);
for (const profile of selectedProfiles()) {
for (const capabilityId of profile.capabilityIds) {
productsByCapability.get(capabilityId)?.add(profile.dataProductId);
}
}
return {
id: geliosProviderPackageV13.id,
version: geliosProviderPackageV13.version,
providerId: geliosProviderPackageV13.providerId,
providerCredential: {
authModeId: "gelios.rest-rotating-bearer.v3",
credentialType: "ndcProviderRotatingAccessApi",
},
capabilities: geliosProviderPackageV13.capabilities
.filter((capability) => productsByCapability.get(capability.id)?.size)
.map((capability) => ({
id: capability.id,
classification: capability.classification,
status: capability.status,
request: {
method: capability.request.method,
url: requestUrl(capability.request),
},
dataProductIds: [...productsByCapability.get(capability.id)].sort(),
})),
publisher: {
nodeType: "n8n-nodes-ndc.ndcDataProductPublish",
credentialType: "ndcDataProductWriterApi",
},
};
}
function requestUrl(request) {
const url = new URL(request.path, request.baseUrl);
for (const [name, value] of Object.entries(request.query || {})) {
url.searchParams.append(name, String(value));
}
return url.toString();
}
function canonicalDigest(value) {
return `sha256:${createHash("sha256").update(JSON.stringify(stableValue(value)), "utf8").digest("hex")}`;
}
function stableValue(value) {
if (Array.isArray(value)) return value.map(stableValue);
if (!value || typeof value !== "object") return value;
return Object.fromEntries(
Object.keys(value).sort().map((key) => [key, stableValue(value[key])]),
);
}
@@ -0,0 +1,208 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import { resolve } from "node:path";
import { validateL2ExecutionPlan } from "../../packages/external-provider-contract/src/index.mjs";
import { geliosProviderPackageV12 } from "../../packages/external-provider-contract/providers/gelios/v12/index.mjs";
const PACKAGE_ID = "gelios.provider.v12";
const PREDECESSOR_VERSION = "12.0.0";
const TARGET_VERSION = "12.0.1";
const UNITS_CAPABILITY_ID = "gelios.units.current.read";
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || "../NODEDC_ENGINE_INFRA",
);
const executionCatalogPath = resolve(
engineRoot,
"nodedc-source/server/assets/execution-plans/v1/catalog.json",
);
const securityCatalogPath = resolve(
engineRoot,
"nodedc-source/server/assets/provider-packages/v1/catalog.json",
);
if (
geliosProviderPackageV12.id !== PACKAGE_ID
|| geliosProviderPackageV12.version !== TARGET_VERSION
) {
throw new Error("gelios_v12_units_items_source_version_mismatch");
}
const sourceCapabilities = new Map(
geliosProviderPackageV12.capabilities.map((capability) => [
capability.id,
capability,
]),
);
const unitsCapability = sourceCapabilities.get(UNITS_CAPABILITY_ID);
if (
!unitsCapability
|| unitsCapability.request.response.collectionPaths[0] !== "items"
) {
throw new Error("gelios_v12_units_items_source_contract_invalid");
}
const executionCatalog = JSON.parse(
await readFile(executionCatalogPath, "utf8"),
);
const executionPackage = requirePackage(executionCatalog, "execution");
assertMigratableVersion(executionPackage.version, "execution");
executionPackage.version = TARGET_VERSION;
executionPackage.contractDigest = canonicalDigest(geliosProviderPackageV12);
executionPackage.capabilities = geliosProviderPackageV12.capabilities.map(
(capability) => ({
id: capability.id,
contractDigest: canonicalDigest(capability),
requestDigest: canonicalDigest(capability.request),
method: capability.request.method,
url: requestUrl(capability.request),
}),
);
for (const profile of executionPackage.profiles) {
const plan = profile.executionPlanTemplate;
if (!plan) throw new Error(`gelios_v12_registered_plan_missing:${profile.id}`);
if (plan.compilerVersion !== "1.4.0") {
throw new Error(`gelios_v12_registered_plan_compiler_drift:${profile.id}`);
}
plan.package.version = TARGET_VERSION;
plan.artifacts.packageDigest = canonicalDigest(geliosProviderPackageV12);
for (const step of plan.steps) {
const capabilityId = step.config?.capabilityId;
if (!capabilityId) continue;
const capability = sourceCapabilities.get(capabilityId);
if (!capability) {
throw new Error(
`gelios_v12_registered_plan_capability_missing:${profile.id}:${capabilityId}`,
);
}
step.config.capabilityDigest = canonicalDigest(capability);
if (step.kind === "provider_request") {
step.config.request = structuredClone(capability.request);
} else if (step.kind === "extract_items") {
step.config.response = structuredClone(capability.request.response);
}
}
const stepsById = new Map(plan.steps.map((step) => [step.id, step]));
for (const node of plan.graphBlueprint.nodes) {
const step = stepsById.get(node.stepId);
if (!step) {
throw new Error(
`gelios_v12_registered_plan_blueprint_step_missing:${profile.id}:${node.stepId}`,
);
}
node.configDigest = canonicalDigest({
stepConfig: step.config,
...(node.adapterConfig ? { adapterConfig: node.adapterConfig } : {}),
});
}
plan.graphBlueprint.blueprintDigest = digestWithout(
plan.graphBlueprint,
"blueprintDigest",
);
plan.executionPlanDigest = digestWithout(plan, "executionPlanDigest");
const validation = validateL2ExecutionPlan(plan);
if (!validation.ok) {
throw new Error(
`gelios_v12_registered_plan_invalid:${profile.id}:`
+ validation.errors.join(","),
);
}
}
const technicalProfile = executionPackage.profiles.find(
(profile) => profile.id === "gelios.units.profile.cold.v1",
);
const technicalExtract = technicalProfile?.executionPlanTemplate?.steps.find(
(step) => (
step.kind === "extract_items"
&& step.config?.capabilityId === UNITS_CAPABILITY_ID
),
);
if (technicalExtract?.config?.response?.collectionPaths?.[0] !== "items") {
throw new Error("gelios_v12_technical_profile_items_envelope_missing");
}
const securityCatalog = JSON.parse(
await readFile(securityCatalogPath, "utf8"),
);
const securityPackage = requirePackage(securityCatalog, "security");
assertMigratableVersion(securityPackage.version, "security");
securityPackage.version = TARGET_VERSION;
await writeFile(
executionCatalogPath,
`${JSON.stringify(executionCatalog, null, 2)}\n`,
);
await writeFile(
securityCatalogPath,
`${JSON.stringify(securityCatalog, null, 2)}\n`,
);
console.log(JSON.stringify({
ok: true,
packageId: PACKAGE_ID,
predecessorVersion: PREDECESSOR_VERSION,
targetVersion: TARGET_VERSION,
executionCatalogPath,
securityCatalogPath,
registeredProfiles: executionPackage.profiles.length,
technicalProfile: technicalProfile.id,
collectionPaths: technicalExtract.config.response.collectionPaths,
compilerVersion: technicalProfile.executionPlanTemplate.compilerVersion,
}, null, 2));
function requirePackage(catalog, kind) {
const matches = catalog.packages.filter(
(providerPackage) => providerPackage.id === PACKAGE_ID,
);
if (matches.length !== 1) {
throw new Error(`gelios_v12_${kind}_package_cardinality_invalid`);
}
return matches[0];
}
function assertMigratableVersion(version, kind) {
if (![PREDECESSOR_VERSION, TARGET_VERSION].includes(version)) {
throw new Error(
`gelios_v12_${kind}_package_version_drift:${String(version)}`,
);
}
}
function requestUrl(request) {
const url = new URL(request.path, request.baseUrl);
for (const [name, value] of Object.entries(request.query || {})) {
url.searchParams.append(name, String(value));
}
return url.toString();
}
function digestWithout(value, key) {
const descriptor = structuredClone(value);
delete descriptor[key];
return canonicalDigest(descriptor);
}
function canonicalDigest(value) {
return `sha256:${createHash("sha256").update(
JSON.stringify(stableValue(value)),
"utf8",
).digest("hex")}`;
}
function stableValue(value) {
if (Array.isArray(value)) return value.map(stableValue);
if (!value || typeof value !== "object") return value;
return Object.fromEntries(
Object.keys(value)
.filter((key) => value[key] !== undefined)
.sort()
.map((key) => [key, stableValue(value[key])]),
);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,130 @@
import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-l1-agent-init-concurrency-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-l1-agent-init-concurrency-20991231-999"
SOURCE_COMMIT = "c4077fe0d8d824fa58616eeb986dc78ca43070da"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_l1_agent_init_concurrency",
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 EngineL1AgentInitConcurrencyArtifactTest(unittest.TestCase):
def require_target_commit(self):
current = subprocess.run(
["git", "-C", str(ENGINE_ROOT), "rev-parse", "HEAD"],
check=True,
capture_output=True,
text=True,
).stdout.strip()
if current != SOURCE_COMMIT:
self.skipTest("historical Engine L1 agent-init source has advanced")
def build(self, artifact_dir):
self.require_target_commit()
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_PATH), PATCH_ID],
check=True,
capture_output=True,
text=True,
env=environment,
)
return json.loads(completed.stdout)
def test_artifact_is_exact_deterministic_and_runner_accepted(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-l1-agent-init-",
) 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["sourceCommit"], SOURCE_COMMIT)
self.assertEqual(first_artifact.read_bytes(), second_artifact.read_bytes())
self.assertEqual(
first["sha256"],
hashlib.sha256(first_artifact.read_bytes()).hexdigest(),
)
self.assertFalse(first["n8nCoreChanged"])
manifest, entries, payload = RUNNER.load_artifact(
first_artifact,
root / "loaded",
)
self.assertEqual(manifest["component"], "engine")
self.assertEqual(manifest["type"], "app-overlay")
self.assertEqual(tuple(entries), tuple(first["entries"]))
self.assertEqual(
RUNNER.component_services("engine", entries),
("nodedc-backend", "app"),
)
self.assertEqual(
RUNNER.component_healthchecks(
"engine",
entries,
("nodedc-backend", "app"),
),
(
"http://127.0.0.1:8080/",
"http://127.0.0.1:3001/health",
),
)
self.assertTrue(RUNNER.component_publish_dist("engine", entries))
self.assertEqual(RUNNER.component_builds("engine", entries), ())
payload_files = {
path.relative_to(payload).as_posix()
for path in payload.rglob("*")
if path.is_file()
}
self.assertEqual(payload_files, set(first["targetSha256"]))
for relative_path, expected in first["targetSha256"].items():
self.assertEqual(
hashlib.sha256((payload / relative_path).read_bytes()).hexdigest(),
expected,
)
self.assertTrue(all("/server/data/" not in path for path in payload_files))
self.assertTrue(all("/tests/" not in path for path in payload_files))
self.assertTrue(all(not path.endswith(".env") for path in payload_files))
self.assertTrue(all("n8n-data" not in path for path in payload_files))
with tarfile.open(first_artifact, "r:gz") as archive:
for member in archive.getmembers():
self.assertIn(member.type, (tarfile.REGTYPE, tarfile.DIRTYPE))
self.assertEqual(member.uid, 0)
self.assertEqual(member.gid, 0)
self.assertEqual(member.mtime, 0)
self.assertNotIn(".DS_Store", member.name)
self.assertNotIn("__MACOSX", member.name)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,284 @@
import hashlib
import importlib.machinery
import importlib.util
import io
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from contextlib import redirect_stdout
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = (
SCRIPT_DIR
/ "build-engine-mcp-gelios-units-items-envelope-artifact.mjs"
)
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-mcp-gelios-units-items-envelope-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_mcp_gelios_units_items",
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 EngineMcpGeliosUnitsItemsEnvelopeTest(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_PATH), PATCH_ID],
check=True,
capture_output=True,
text=True,
env=environment,
)
return json.loads(completed.stdout)
def test_builder_emits_exact_deterministic_catalog_slice(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-gelios-units-items-builder-"
) 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["sha256"],
hashlib.sha256(first_artifact.read_bytes()).hexdigest(),
)
self.assertEqual(first["services"], ["nodedc-backend"])
self.assertEqual(first["mcpVersion"], "0.12.0")
self.assertEqual(
first["registeredProfile"],
"gelios.units.profile.cold.v1",
)
self.assertEqual(first["responseCollectionPath"], "items")
self.assertEqual(first["existingMaterializerReused"], True)
self.assertEqual(first["engineRuntimeCodeChanged"], False)
self.assertEqual(first["n8nCoreChanged"], False)
self.assertEqual(first["l2GraphChanged"], False)
extract = root / "extract"
with tarfile.open(first_artifact, "r:gz") as archive:
archive.extractall(extract, filter="data")
entries = tuple(
(extract / "files.txt").read_text(encoding="utf-8").splitlines()
)
self.assertEqual(
entries,
RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_ARTIFACT_ENTRIES,
)
self.assertTrue(
RUNNER.is_engine_mcp_gelios_units_items_slice(
"engine",
entries,
)
)
self.assertEqual(
RUNNER.component_services("engine", entries),
("nodedc-backend",),
)
RUNNER.validate_engine_mcp_gelios_units_items_slice(
extract / "payload",
entries,
)
def test_preflight_requires_exact_registered_profiles_predecessor(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-gelios-units-items-preflight-"
) as directory:
root = Path(directory)
all_live = {
**RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_PREDECESSOR_SHA256,
**RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_FOUNDATION_SHA256,
}
for relative_path in all_live:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("live\n", encoding="utf-8")
def exact_hash(path):
relative_path = Path(path).relative_to(root).as_posix()
return all_live[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_hash),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = (
RUNNER
.preflight_engine_mcp_gelios_units_items_predecessor()
)
self.assertEqual(
result["mode"],
(
"registered-profiles-v2-to-"
"gelios-v12.0.1-units-items-envelope"
),
)
self.assertEqual(
result["new_paths"],
RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_NEW_PATHS,
)
changed = next(iter(
RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_PREDECESSOR_SHA256
))
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(
RUNNER,
"sha256_file",
side_effect=lambda path: (
"0" * 64
if Path(path).relative_to(root).as_posix() == changed
else exact_hash(path)
),
),
):
with self.assertRaises(RUNNER.DeployError):
(
RUNNER
.preflight_engine_mcp_gelios_units_items_predecessor()
)
def test_plan_renders_exact_provider_package_patch_boundary(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-gelios-units-items-plan-"
) as directory:
root = Path(directory)
built = self.build(root / "artifacts")
artifact = Path(built["artifact"])
live_root = root / "live"
live_root.mkdir()
preflight = {
"mode": (
"registered-profiles-v2-to-"
"gelios-v12.0.1-units-items-envelope"
),
"predecessor_sha256": dict(
RUNNER
.ENGINE_MCP_GELIOS_UNITS_ITEMS_PREDECESSOR_SHA256
),
"foundation_sha256": dict(
RUNNER
.ENGINE_MCP_GELIOS_UNITS_ITEMS_FOUNDATION_SHA256
),
"target_sha256": dict(
RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_TARGET_SHA256
),
"new_paths": (
RUNNER.ENGINE_MCP_GELIOS_UNITS_ITEMS_NEW_PATHS
),
"backend_mode": "verified-derived-retry",
}
output = io.StringIO()
with (
mock.patch.object(RUNNER, "validate_artifact_location"),
mock.patch.object(RUNNER, "ensure_layout"),
mock.patch.object(RUNNER, "TMP_DIR", root),
mock.patch.object(
RUNNER,
"component_root",
return_value=live_root,
),
mock.patch.object(
RUNNER,
"component_compose_root",
return_value=live_root,
),
mock.patch.object(
RUNNER,
"preflight_engine_mcp_gelios_units_items_predecessor",
return_value=preflight,
),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(RUNNER, "state_has_sha", return_value=False),
mock.patch.object(
RUNNER,
"state_has_patch_id",
return_value=False,
),
redirect_stdout(output),
):
RUNNER.plan_artifact(artifact)
plan = output.getvalue()
self.assertIn("services=nodedc-backend", plan)
self.assertIn("engine_mcp_version=0.12.0", plan)
self.assertIn(
"engine_mcp_provider_package=gelios.provider.v12@12.0.1",
plan,
)
self.assertIn(
"engine_mcp_registered_profile=gelios.units.profile.cold.v1",
plan,
)
self.assertIn("engine_mcp_response_collection_path=items", plan)
self.assertIn("engine_mcp_existing_materializer=reused", plan)
self.assertIn("engine_mcp_runtime_code_changed=no", plan)
self.assertIn("engine_mcp_provider_endpoints_changed=no", plan)
self.assertIn("l2_graph=untouched", plan)
self.assertIn("n8n_core=untouched", plan)
self.assertIn("foundry=untouched", plan)
self.assertIn("state=new", plan)
def test_live_acceptance_probes_catalog_and_tools(self):
expected_live = (
"engine-mcp-gelios-units-items:0.12.0:"
"gelios.provider.v12@12.0.1:technical-profile:items"
)
with (
mock.patch.object(RUNNER, "component_root", return_value=ENGINE_ROOT),
mock.patch.object(
RUNNER,
"engine_backend_container_id",
return_value="backend",
),
mock.patch.object(
RUNNER,
"run_engine_backend_probe",
return_value=expected_live,
) as backend_probe,
):
result = RUNNER.accept_engine_mcp_gelios_units_items_runtime()
self.assertEqual(result["live"], expected_live)
probe_source = backend_probe.call_args.args[0][-1]
self.assertIn("engine_list_l2_execution_profiles", probe_source)
self.assertIn("engine_plan_registered_l2_execution", probe_source)
self.assertIn("gelios.units.profile.cold.v1", probe_source)
self.assertIn("collectionPaths?.[0]!=='items'", probe_source)
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -0,0 +1,316 @@
import hashlib
import importlib.machinery
import importlib.util
import io
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from contextlib import redirect_stdout
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = (
SCRIPT_DIR
/ "build-engine-mcp-registered-execution-profiles-artifact.mjs"
)
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-mcp-registered-execution-profiles-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_mcp_registered_execution_profiles",
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 EngineMcpRegisteredExecutionProfilesTest(unittest.TestCase):
def require_current_target_source(self):
for relative_path, expected in (
RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_TARGET_SHA256.items()
):
path = ENGINE_ROOT / relative_path
if (
not path.is_file()
or hashlib.sha256(path.read_bytes()).hexdigest() != expected
):
self.skipTest("Registered execution profiles source advanced")
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_PATH), PATCH_ID],
check=True,
capture_output=True,
text=True,
env=environment,
)
return json.loads(completed.stdout)
def test_builder_emits_exact_deterministic_backend_slice(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-registered-profiles-builder-"
) 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["sha256"],
hashlib.sha256(first_artifact.read_bytes()).hexdigest(),
)
self.assertEqual(first["services"], ["nodedc-backend"])
self.assertEqual(first["mcpVersion"], "0.12.0")
self.assertEqual(first["registeredProfiles"], 6)
self.assertEqual(first["existingMaterializerReused"], True)
self.assertEqual(
first["nodeIntelligenceAttestationChanged"],
True,
)
self.assertEqual(first["nodeIntelligenceImageChanged"], False)
self.assertEqual(first["nodeIntelligenceSourceChanged"], False)
self.assertEqual(first["n8nCoreChanged"], False)
self.assertEqual(first["l2GraphChanged"], False)
extract = root / "extract"
with tarfile.open(first_artifact, "r:gz") as archive:
archive.extractall(extract, filter="data")
entries = tuple(
(extract / "files.txt").read_text(encoding="utf-8").splitlines()
)
self.assertEqual(
entries,
RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_ARTIFACT_ENTRIES,
)
self.assertTrue(
RUNNER.is_engine_mcp_registered_execution_profiles_slice(
"engine",
entries,
)
)
self.assertEqual(
RUNNER.component_services("engine", entries),
("nodedc-backend",),
)
RUNNER.validate_engine_mcp_registered_execution_profiles_slice(
extract / "payload",
entries,
)
def test_preflight_requires_exact_046_predecessor_and_absent_new_paths(self):
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-registered-profiles-preflight-"
) as directory:
root = Path(directory)
all_live = {
**RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_PREDECESSOR_SHA256,
**RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_FOUNDATION_SHA256,
}
for relative_path in all_live:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("live\n", encoding="utf-8")
def exact_hash(path):
relative_path = Path(path).relative_to(root).as_posix()
return all_live[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_hash),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = (
RUNNER
.preflight_engine_mcp_registered_execution_profiles_predecessor()
)
self.assertEqual(
result["mode"],
"gelios-items-envelope-v12-to-registered-profiles-v2-attested",
)
self.assertEqual(
result["new_paths"],
RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_NEW_PATHS,
)
new_path = (
root
/ RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_NEW_PATHS[0]
)
new_path.parent.mkdir(parents=True, exist_ok=True)
new_path.write_text("unexpected\n", encoding="utf-8")
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_hash),
):
with self.assertRaises(RUNNER.DeployError):
(
RUNNER
.preflight_engine_mcp_registered_execution_profiles_predecessor()
)
def test_plan_renders_exact_server_side_planning_boundary(self):
self.require_current_target_source()
with tempfile.TemporaryDirectory(
prefix="nodedc-engine-registered-profiles-plan-"
) as directory:
root = Path(directory)
built = self.build(root / "artifacts")
artifact = Path(built["artifact"])
live_root = root / "live"
live_root.mkdir()
preflight = {
"mode":
"gelios-items-envelope-v12-to-registered-profiles-v2-attested",
"predecessor_sha256": dict(
RUNNER
.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_PREDECESSOR_SHA256
),
"foundation_sha256": dict(
RUNNER
.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_FOUNDATION_SHA256
),
"target_sha256": dict(
RUNNER
.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_TARGET_SHA256
),
"new_paths": (
RUNNER
.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_NEW_PATHS
),
"backend_mode": "verified-derived-retry",
}
output = io.StringIO()
with (
mock.patch.object(RUNNER, "validate_artifact_location"),
mock.patch.object(RUNNER, "ensure_layout"),
mock.patch.object(RUNNER, "TMP_DIR", root),
mock.patch.object(
RUNNER,
"component_root",
return_value=live_root,
),
mock.patch.object(
RUNNER,
"component_compose_root",
return_value=live_root,
),
mock.patch.object(
RUNNER,
"preflight_engine_mcp_registered_execution_profiles_predecessor",
return_value=preflight,
),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(RUNNER, "state_has_sha", return_value=False),
mock.patch.object(
RUNNER,
"state_has_patch_id",
return_value=False,
),
redirect_stdout(output),
):
RUNNER.plan_artifact(artifact)
plan = output.getvalue()
self.assertIn("services=nodedc-backend", plan)
self.assertIn("engine_mcp_version=0.12.0", plan)
self.assertIn("engine_mcp_registered_profiles=6", plan)
self.assertIn("engine_mcp_target_scope=server-derived", plan)
self.assertIn("engine_mcp_existing_materializer=reused", plan)
self.assertIn("engine_mcp_provider_endpoints_included=no", plan)
self.assertIn(
"engine_node_intelligence_attestation=updated",
plan,
)
self.assertIn("engine_node_intelligence_image=untouched", plan)
self.assertIn("l2_graph=untouched", plan)
self.assertIn("n8n_core=untouched", plan)
self.assertIn("foundry=untouched", plan)
self.assertIn("state=new", plan)
def test_live_acceptance_probes_tools_catalog_and_target_rebinding(self):
self.require_current_target_source()
expected_live = (
"engine-mcp-registered-execution-profiles:"
"0.12.0:profiles-6:target-scope:existing-materializer"
)
with (
mock.patch.object(RUNNER, "component_root", return_value=ENGINE_ROOT),
mock.patch.object(
RUNNER,
"engine_backend_container_id",
return_value="backend",
),
mock.patch.object(
RUNNER,
"run_engine_backend_probe",
return_value=expected_live,
) as backend_probe,
):
result = (
RUNNER.accept_engine_mcp_registered_execution_profiles_runtime()
)
self.assertEqual(result["live"], expected_live)
probe_source = backend_probe.call_args.args[0][-1]
self.assertIn("engine_list_l2_execution_profiles", probe_source)
self.assertIn("engine_plan_registered_l2_execution", probe_source)
self.assertIn("tenant-probe", probe_source)
self.assertIn("ndc-credref:engine-target-", probe_source)
def test_target_gateway_matches_node_intelligence_attestation(self):
descriptor_path = (
ENGINE_ROOT
/ RUNNER.ENGINE_NODE_INTELLIGENCE_DESCRIPTOR_REL
)
descriptor = RUNNER.read_engine_node_intelligence_descriptor(
descriptor_path,
"registered profiles target node-intelligence descriptor",
)
with mock.patch.object(
RUNNER,
"component_root",
return_value=ENGINE_ROOT,
):
gateway_sha256 = (
RUNNER.validate_installed_engine_node_intelligence_source(
descriptor,
)
)
self.assertEqual(
gateway_sha256,
RUNNER.ENGINE_MCP_REGISTERED_EXECUTION_PROFILES_TARGET_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -147,15 +147,15 @@ class EngineNodeIntelligenceTest(unittest.TestCase):
)
self.assertEqual(actual, descriptor)
def test_gateway_accepts_registered_0_11_and_rejects_unknown_successors(self):
def test_gateway_accepts_registered_0_12_and_rejects_unknown_successors(self):
with tempfile.TemporaryDirectory() as directory:
payload, descriptor = self.make_activation_payload(Path(directory))
gateway = payload / RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
gateway_text = gateway.read_text(encoding="utf-8")
self.assertIn("const ENGINE_AGENT_MCP_VERSION = '0.11.0'", gateway_text)
self.assertIn("const ENGINE_AGENT_MCP_VERSION = '0.12.0'", gateway_text)
gateway.write_text(
gateway_text.replace(
"const ENGINE_AGENT_MCP_VERSION = '0.11.0'",
"const ENGINE_AGENT_MCP_VERSION = '0.12.0'",
"const ENGINE_AGENT_MCP_VERSION = '9.9.9'",
),
encoding="utf-8",