feat(platform): complete the Gelios external data loop

This commit is contained in:
Codex
2026-07-20 20:45:05 +03:00
parent def9a24e0d
commit 8a7465cf0e
66 changed files with 5730 additions and 123 deletions
+22
View File
@@ -172,6 +172,28 @@ runtime and descriptor equality. The ordinary overlay backup is the automatic
rollback source; rollback restores the predecessor gateway and descriptor
together before recreating the same backend service.
The successor autonomy/provider-v5 slice keeps MCP authority explicit without
turning every write into a second permission dialogue. MCP tool availability is
the capability boundary, while the user's current objective is the intent
boundary; Engine L2 may act autonomously only inside their intersection. A
graph `plan` remains a mandatory machine barrier whose target, diff, revision
and blockers are inspected by the agent. It is not a repeated approval prompt
after an implementation objective is already authorized. Retries must add new
evidence or change the attempted variant, and three identical failures without
new evidence or state change are a critical stop. The slice also advances the
installer to `0.1.6` and adds `gelios.provider.v5 ->
fleet.positions.current.v4` beside the immutable v4/v3 rollback line:
```bash
node infra/deploy-runner/build-engine-mcp-autonomy-provider-v5-artifact.mjs \
20260720-004
```
Its seven-entry allowlist recreates only `nodedc-backend`; n8n, L1, databases,
credential values and the node-intelligence image remain outside the change.
The runner accepts both the exact target and the exact predecessor after an
automatic rollback, and rejects every mixed state.
For `platform` artifacts, the allowlist includes the versioned Ontology Core,
the frozen legacy Gelios compatibility service, and the provider-neutral
External Data Plane sources. The Gelios service remains reproducible only to
@@ -0,0 +1,164 @@
#!/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 here = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(here, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactRoot = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"),
);
const [patchId = "", ...extra] = process.argv.slice(2);
if (extra.length || !/^engine-composite-provider-v4-\d{8}-\d{3}$/.test(patchId)) {
throw new Error(
"usage: build-engine-composite-provider-v4-artifact.mjs " +
"<engine-composite-provider-v4-YYYYMMDD-NNN>",
);
}
const targetSha256 = Object.freeze({
"nodedc-source/server/assets/provider-packages/v1/catalog.json":
"9c931f9abfcadb5b34a8a854c2efb8fd79913e000eecf0967d1b7c500bf9a56a",
"nodedc-source/server/dataProductPublishGrant/providerCatalog.js":
"689c6fbf695e582d983159973a21142787d1b19bb1d343da4c62c03092ac291f",
"nodedc-source/server/dataProductPublishGrant/service.js":
"83f045f4e0f332644310172ed51bb652d808bf04155b11c02e46bdffc95f7220",
"nodedc-source/server/dataProductPublishGrant/store.js":
"98662da6acd0489a9cae4b726eb61ce89d9b2c788b2ea95433e9c4f02930c095",
});
const entries = Object.freeze(Object.keys(targetSha256));
const artifact = join(artifactRoot, `nodedc-${patchId}.tgz`);
await assertFresh(artifact);
await assertExactSources();
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-composite-provider-v4-"));
try {
const payload = join(stage, "payload");
for (const relativePath of entries) {
const source = join(engineRoot, relativePath);
const destination = join(payload, relativePath);
await mkdir(dirname(destination), { recursive: true });
await copyFile(source, destination, 0);
}
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(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
sha256: digest(await readFile(artifact)),
entries,
targetSha256,
services: ["nodedc-backend"],
transition: "exact-v3-to-v4",
providerPackage: "gelios.provider.v4",
capabilities: [
"gelios.monitoring_config.current.read",
"gelios.units.current.read",
],
dataProductId: "fleet.positions.current.v3",
credentialValues: "preserved",
untouched: ["n8n", "L1 graph", "Engine UI", "databases"],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(targetSha256)) {
const path = join(engineRoot, relativePath);
const info = await lstat(path);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_composite_provider_source_unsafe:${relativePath}`);
}
const actual = digest(await readFile(path));
if (actual !== expected) {
throw new Error(
`engine_composite_provider_target_mismatch:${relativePath}:` +
`expected=${expected}:actual=${actual}`,
);
}
}
const catalog = JSON.parse(await readFile(join(engineRoot, entries[0]), "utf8"));
const provider = catalog?.packages?.[0];
const capabilityIds = provider?.capabilities?.map((item) => item.id);
const requestUrls = provider?.capabilities?.map((item) => item.request?.url);
if (
catalog?.schemaVersion !== "nodedc.engine.provider-security-catalog/v1" ||
provider?.id !== "gelios.provider.v4" ||
provider?.version !== "4.0.0" ||
provider?.providerCredential?.credentialType !== "httpBearerAuth" ||
JSON.stringify(capabilityIds) !== JSON.stringify([
"gelios.monitoring_config.current.read",
"gelios.units.current.read",
]) ||
JSON.stringify(requestUrls) !== JSON.stringify([
"https://api.geliospro.com/api/v1/users/me/monitoring-config",
"https://api.geliospro.com/api/v1/units?incltrip=true",
]) ||
provider?.capabilities?.some(
(item) => item.dataProductIds?.length !== 1 ||
item.dataProductIds[0] !== "fleet.positions.current.v3",
)
) {
throw new Error("engine_composite_provider_catalog_projection_mismatch");
}
}
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,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -17,6 +17,7 @@ const previouslyIssuedPatchIds = new Set([
'engine-data-product-publish-grant-20260717-001',
'engine-data-product-publish-grant-20260717-002',
])
const compositeProviderCatalogTargetSha256 = '9c931f9abfcadb5b34a8a854c2efb8fd79913e000eecf0967d1b7c500bf9a56a'
if (extra.length || !/^engine-data-product-publish-grant-\d{8}-\d{3}$/.test(patchId)) {
throw new Error('usage: build-engine-data-product-publish-grant-artifact.mjs <fresh-patch-id>')
@@ -109,6 +110,13 @@ try {
'nodedc-source/dist',
'nodedc-source/server/tests',
],
providerPackage: 'gelios.provider.v4',
providerRequests: [
'https://api.geliospro.com/api/v1/users/me/monitoring-config',
'https://api.geliospro.com/api/v1/units?incltrip=true',
],
dataProductId: 'fleet.positions.current.v3',
credentialValues: 'preserved',
preservedPredecessor: Object.keys(credentialSinkPredecessorSha256),
}, null, 2))
} finally {
@@ -116,10 +124,14 @@ try {
}
async function assertSourceBoundary() {
for (const [relativePath, expectedSha256] of Object.entries(credentialSinkPredecessorSha256)) {
const bytes = await readFile(join(engineRoot, relativePath))
if (digest(bytes) !== expectedSha256) {
throw new Error(`engine_credential_sink_predecessor_drift:${relativePath}`)
// These files are deliberately excluded from the artifact. Their exact
// installed predecessor is verified by the root-owned runner during plan
// and apply; the local builder only proves that it cannot package a link or
// another unsafe filesystem object in their place.
for (const relativePath of Object.keys(credentialSinkPredecessorSha256)) {
const info = await lstat(join(engineRoot, relativePath))
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_credential_sink_predecessor_unsafe:${relativePath}`)
}
}
const runtimeOverridePath = join(
@@ -129,6 +141,13 @@ async function assertSourceBoundary() {
if (await readFile(runtimeOverridePath, 'utf8') !== publishGrantRuntimeOverride) {
throw new Error('engine_publish_grant_runtime_override_mismatch')
}
const catalogPath = join(
engineRoot,
'nodedc-source/server/assets/provider-packages/v1/catalog.json',
)
if (digest(await readFile(catalogPath)) !== compositeProviderCatalogTargetSha256) {
throw new Error('engine_composite_provider_catalog_target_mismatch')
}
const indexSource = await readFile(join(engineRoot, 'nodedc-source/server/index.js'), 'utf8')
if (!indexSource.includes("app.use('/api/engine-agent-mcp', engineAgentMcpRouter)")) {
@@ -175,6 +194,32 @@ async function assertSourceBoundary() {
if (JSON.stringify(grantFiles) !== JSON.stringify(expectedGrantFiles)) {
throw new Error('engine_publish_grant_source_set_mismatch')
}
const providerCatalogSource = await readFile(join(grantDirectory, 'providerCatalog.js'), 'utf8')
const grantServiceSource = await readFile(join(grantDirectory, 'service.js'), 'utf8')
const grantStoreSource = await readFile(join(grantDirectory, 'store.js'), 'utf8')
for (const marker of [
'function capabilityRequests(capability)',
'function exactHttpRequestUrl(n8n)',
'capabilityIds',
'providerRequestNodeIds',
'providerCredentialRefs.size !== 1',
]) {
if (!providerCatalogSource.includes(marker)) {
throw new Error(`engine_composite_provider_resolver_missing:${marker}`)
}
}
if (
!grantServiceSource.includes('capabilities: descriptor.capabilityIds')
|| !grantServiceSource.includes('providerRequestNodeIds: descriptor.providerRequestNodeIds')
) {
throw new Error('engine_composite_provider_plan_projection_missing')
}
if (
!grantStoreSource.includes('Array.isArray(raw.capabilityIds)')
|| !grantStoreSource.includes('Array.isArray(raw.providerRequestNodeIds)')
) {
throw new Error('engine_composite_provider_store_projection_missing')
}
for (const entry of entries) {
const source = resolve(engineRoot, entry)
const info = await lstat(source)
@@ -0,0 +1,157 @@
#!/usr/bin/env node
import { createHash } from 'node:crypto'
import { spawnSync } from 'node:child_process'
import { cp, 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 here = dirname(fileURLToPath(import.meta.url))
const platformRoot = resolve(here, '../..')
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || resolve(platformRoot, '../NODEDC_ENGINE_INFRA'),
)
const canonicalArtifactRoot = resolve(here, '../deploy-artifacts')
const artifactRoot = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || canonicalArtifactRoot)
const [transitionId = '20260720-004', ...extra] = process.argv.slice(2)
if (extra.length || !/^\d{8}-[0-9]{3}$/.test(transitionId)) {
throw new Error('usage: build-engine-mcp-autonomy-provider-v5-artifact.mjs [YYYYMMDD-NNN]')
}
const id = `engine-mcp-autonomy-provider-v5-${transitionId}`
const target = join(artifactRoot, `nodedc-${id}.tgz`)
const predecessorArtifact = join(
canonicalArtifactRoot,
'nodedc-engine-mcp-control-plane-20260718-003.tgz',
)
const predecessorArtifactSha256 = '249aef9527666c562e9648b15737e66cc5c1dc7c0788b58ea714da270b5eb4ba'
const descriptorRel = 'nodedc-source/services/node-intelligence/activation.json'
const gatewayRel = 'nodedc-source/server/routes/engineAgentGateway.js'
const files = [
'nodedc-source/server/assets/engine-agent-npm/bin/nodedc-engine-codex-agent.mjs',
'nodedc-source/server/assets/engine-agent-npm/package.json',
'nodedc-source/server/assets/nodedc-engine-codex-agent-0.1.6.tgz',
'nodedc-source/server/assets/provider-packages/v1/catalog.json',
'nodedc-source/server/engineAgents/store.js',
gatewayRel,
descriptorRel,
]
const expectedSha256 = new Map([
[files[0], 'c15c9da4f90f44a4e9e12f3683127e906d614fb98e562faa0c939505c973e074'],
[files[1], '2ca8dcab0fa04bb1b21add1f75a9be61d5aa97753443ee1917302b4e0da5780a'],
[files[2], 'd007a81cb4e4af569b3c54d3869b0f60b5597e3b531bff232145fa1851d8572a'],
[files[3], '63e0741646197f0b1b3c64a4095e1bc8fb3a95ee6caf20b0293f89d869c9e620'],
[files[4], '4cd4bdd5958cfafee184e98a04fe12aa0c1cbe884326beaec63c99f9fff61285'],
[files[5], '5331f6dc8dc306f641370a2968eb025ee3e278e27ae9a217e4cfc2901fec369c'],
])
await assertFresh(target)
assertSha(await readFile(predecessorArtifact), predecessorArtifactSha256, 'predecessor MCP artifact')
const stage = await mkdtemp(join(tmpdir(), 'nodedc-engine-mcp-autonomy-provider-v5-'))
const payload = join(stage, 'payload')
try {
await mkdir(payload, { recursive: true })
for (const rel of files.slice(0, -1)) {
const source = join(engineRoot, rel)
const stat = await lstat(source)
if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`source_boundary_invalid:${rel}`)
assertSha(await readFile(source), expectedSha256.get(rel), rel)
await mkdir(dirname(join(payload, rel)), { recursive: true })
await cp(source, join(payload, rel), { force: false })
}
const descriptor = JSON.parse(extractMember(
predecessorArtifact,
`payload/${descriptorRel}`,
))
if (
descriptor?.action !== 'activate'
|| descriptor?.releaseId !== '2.33.2-974a9fb3492f'
|| descriptor?.source?.gatewaySha256 !== '96c726dab5cf1341f74e6e1095d518058ca320e0dd5738e25bdbe75db1f4fc15'
|| descriptor?.source?.upstreamProjectionSha256 !== '761a874b102a938bc6018159ddacdaac71ad6ae08e9f0f8d7f3b58a0165a5131'
) throw new Error('mcp_autonomy_predecessor_descriptor_mismatch')
descriptor.source.gatewaySha256 = expectedSha256.get(gatewayRel)
await mkdir(dirname(join(payload, descriptorRel)), { recursive: true })
await writeFile(join(payload, descriptorRel), `${JSON.stringify(descriptor, null, 2)}\n`, 'utf8')
await writeFile(join(stage, 'manifest.env'), `id=${id}\ncomponent=engine\ntype=app-overlay\n`, 'utf8')
await writeFile(join(stage, 'files.txt'), `${files.join('\n')}\n`, 'utf8')
await mkdir(artifactRoot, { recursive: true })
run('python3', ['-c', canonicalTarScript(), target, stage])
console.log(JSON.stringify({
ok: true,
id,
artifact: target,
artifactSha256: sha(await readFile(target)),
services: ['nodedc-backend'],
mcpVersion: '0.6.0',
installerVersion: '0.1.6',
authority: 'mcp-capability-intersect-user-objective',
retryBoundary: 'three-identical-failures-without-new-evidence',
providerPackages: ['gelios.provider.v4', 'gelios.provider.v5'],
targetDataProduct: 'fleet.positions.current.v4',
preserved: ['n8n', 'L1', 'node-intelligence image', 'databases', 'credential values'],
files,
}, null, 2))
} finally {
await rm(stage, { recursive: true, force: true })
}
async function assertFresh(path) {
try {
await lstat(path)
} catch (error) {
if (error?.code === 'ENOENT') return
throw error
}
throw new Error('artifact_already_exists')
}
function extractMember(archive, member) {
const script = [
'import pathlib,sys,tarfile',
'p=pathlib.Path(sys.argv[1]); name=sys.argv[2]',
"with tarfile.open(p,'r:gz') as t:",
' m=t.getmember(name)',
" if not m.isfile(): raise SystemExit('member-not-file')",
' f=t.extractfile(m)',
" if f is None: raise SystemExit('member-unreadable')",
' sys.stdout.buffer.write(f.read())',
].join('\n')
return run('python3', ['-c', script, archive, member]).stdout
}
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 assertSha(bytes, expected, label) {
const actual = sha(bytes)
if (!expected || actual !== expected) throw new Error(`${label.replaceAll(' ', '_')}_sha256_mismatch:${actual}`)
}
function sha(bytes) {
return createHash('sha256').update(bytes).digest('hex')
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: 'utf8',
maxBuffer: 128 * 1024 * 1024,
stdio: ['ignore', 'pipe', 'pipe'],
})
if (result.status !== 0) throw new Error(`${command}_failed:${result.stderr || result.stdout}`)
return result
}
@@ -0,0 +1,140 @@
#!/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 here = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(here, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactRoot = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"),
);
const [patchId = "", ...extra] = process.argv.slice(2);
if (extra.length || !/^engine-provider-authority-diagnostics-\d{8}-\d{3}$/.test(patchId)) {
throw new Error(
"usage: build-engine-provider-authority-diagnostics-artifact.mjs " +
"<engine-provider-authority-diagnostics-YYYYMMDD-NNN>",
);
}
const targetSha256 = Object.freeze({
"nodedc-source/server/dataProductPublishGrant/providerCatalog.js":
"1a14299167ebe17efd677fa3c59b84c80e12d6846bac6f40f9bcae0729ab22c6",
});
const entries = Object.freeze(Object.keys(targetSha256));
const artifact = join(artifactRoot, `nodedc-${patchId}.tgz`);
await assertFresh(artifact);
await assertExactSources();
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-provider-authority-diagnostics-"));
try {
const payload = join(stage, "payload");
for (const relativePath of entries) {
const destination = join(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(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
sha256: digest(await readFile(artifact)),
entries,
targetSha256,
services: ["nodedc-backend"],
transition: "exact-safe-provider-authority-reason-codes",
providerPackage: "gelios.provider.v4",
dataProductId: "fleet.positions.current.v3",
credentialValues: "preserved",
untouched: ["L2 graph", "n8n", "L1", "Engine UI", "databases"],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(targetSha256)) {
const sourcePath = join(engineRoot, relativePath);
const info = await lstat(sourcePath);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_provider_authority_diagnostics_source_unsafe:${relativePath}`);
}
const actual = digest(await readFile(sourcePath));
if (actual !== expected) {
throw new Error(
`engine_provider_authority_diagnostics_target_mismatch:${relativePath}:` +
`expected=${expected}:actual=${actual}`,
);
}
const source = await readFile(sourcePath, "utf8");
for (const marker of [
"publish_grant_provider_request_not_exact",
"publish_grant_provider_credential_binding_invalid",
"publish_grant_provider_transport_policy_not_exact",
"publish_grant_provider_request_path_unreachable",
"publish_grant_provider_credential_identity_mismatch",
]) {
if (!source.includes(marker)) {
throw new Error(`engine_provider_authority_diagnostics_marker_missing:${marker}`);
}
}
}
}
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,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -0,0 +1,140 @@
#!/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 here = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(here, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactRoot = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"),
);
const [patchId = "", ...extra] = process.argv.slice(2);
if (extra.length || !/^engine-provider-rotating-slot-\d{8}-\d{3}$/.test(patchId)) {
throw new Error(
"usage: build-engine-provider-rotating-slot-artifact.mjs " +
"<engine-provider-rotating-slot-YYYYMMDD-NNN>",
);
}
const targetSha256 = Object.freeze({
"nodedc-source/server/assets/provider-packages/v1/catalog.json":
"17f3e368f3264cbbd708965c9e1fd735aa974f15a1383bf88cd6d14a43dbf32d",
"nodedc-source/server/dataProductPublishGrant/providerCatalog.js":
"f6cf5f4de9e57f87fb904e2136a9f34d494e1ffc289aec3ed9ed788b5583a062",
});
const entries = Object.freeze(Object.keys(targetSha256));
const artifact = join(artifactRoot, `nodedc-${patchId}.tgz`);
await assertFresh(artifact);
await assertExactSources();
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-provider-rotating-slot-"));
try {
const payload = join(stage, "payload");
for (const relativePath of entries) {
const destination = join(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(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
sha256: digest(await readFile(artifact)),
entries,
targetSha256,
services: ["nodedc-backend"],
transition: "exact-active-credential-slot-alignment",
providerPackage: "gelios.provider.v4",
authModeId: "gelios.rest-rotating-bearer.v3",
credentialSlot: "ndcProviderRotatingAccessApi",
credentialValues: "preserved",
untouched: ["L2 graph", "n8n", "L1", "Engine UI", "databases"],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(targetSha256)) {
const path = join(engineRoot, relativePath);
const info = await lstat(path);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_provider_rotating_slot_source_unsafe:${relativePath}`);
}
const actual = digest(await readFile(path));
if (actual !== expected) {
throw new Error(
`engine_provider_rotating_slot_target_mismatch:${relativePath}:` +
`expected=${expected}:actual=${actual}`,
);
}
}
const catalog = JSON.parse(await readFile(join(engineRoot, entries[0]), "utf8"));
const provider = catalog?.packages?.[0];
if (
provider?.id !== "gelios.provider.v4" ||
provider?.providerCredential?.authModeId !== "gelios.rest-rotating-bearer.v3" ||
provider?.providerCredential?.credentialType !== "ndcProviderRotatingAccessApi"
) {
throw new Error("engine_provider_rotating_slot_catalog_projection_mismatch");
}
}
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,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -0,0 +1,117 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { 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 here = dirname(fileURLToPath(import.meta.url));
const platformRoot = resolve(here, "../..");
const artifactRoot = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"),
);
const [transitionId = "20260719-006", ...extra] = process.argv.slice(2);
if (extra.length || !/^\d{8}-[0-9]{3}$/.test(transitionId)) {
throw new Error("usage: build-engine-provider-security-catalog-artifact.mjs [YYYYMMDD-NNN]");
}
const id = `engine-provider-security-catalog-${transitionId}`;
const target = join(artifactRoot, `nodedc-${id}.tgz`);
const file = "nodedc-source/server/assets/provider-packages/v1/catalog.json";
const expectedSha256 = "992159fc457ec76ce1f45aad337604c8a72b29252d44fbccda515f0fd6ea6428";
const catalogBytes = Buffer.from(`${JSON.stringify({
schemaVersion: "nodedc.engine.provider-security-catalog/v1",
packages: [{
id: "gelios.provider.v3",
version: "3.0.0",
providerId: "gelios",
providerCredential: {
authModeId: "gelios.rest-rotating-bearer.v3",
credentialType: "httpBearerAuth",
},
capabilities: [{
id: "gelios.units.current.read",
classification: "read",
status: "implemented",
request: {
method: "GET",
url: "https://api.geliospro.com/api/v1/units",
},
dataProductIds: ["fleet.positions.current.v2"],
}],
publisher: {
nodeType: "n8n-nodes-ndc.ndcDataProductPublish",
credentialType: "ndcDataProductWriterApi",
},
}],
}, null, 2)}\n`, "utf8");
await assertFresh(target);
if (sha(catalogBytes) !== expectedSha256) throw new Error(`pinned_catalog_sha256_mismatch:${file}`);
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-provider-security-catalog-"));
const payload = join(stage, "payload");
try {
await mkdir(dirname(join(payload, file)), { recursive: true });
await writeFile(join(payload, file), catalogBytes, { flag: "wx", mode: 0o644 });
await writeFile(join(stage, "manifest.env"), `id=${id}\ncomponent=engine\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${file}\n`, "utf8");
await mkdir(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), target, stage]);
console.log(JSON.stringify({
ok: true,
id,
artifact: target,
artifactSha256: sha(await readFile(target)),
services: ["nodedc-backend"],
providerPackage: "gelios.provider.v3",
providerCredential: "httpBearerAuth",
endpoint: "https://api.geliospro.com/api/v1/units",
dataProductId: "fleet.positions.current.v2",
preserved: ["n8n", "L1 graph", "Engine UI", "databases", "provider credential values"],
files: [file],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
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],'wb') 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 sha(value) {
return createHash("sha256").update(value).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
return result;
}
@@ -0,0 +1,138 @@
#!/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 here = dirname(fileURLToPath(import.meta.url));
const workspaceRoot = resolve(here, "../../..");
const engineRoot = resolve(
process.env.NODEDC_ENGINE_SOURCE_ROOT || join(workspaceRoot, "NODEDC_ENGINE_INFRA"),
);
const artifactRoot = resolve(
process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"),
);
const [patchId = "", ...extra] = process.argv.slice(2);
if (extra.length || !/^engine-provider-target-host-policy-\d{8}-\d{3}$/.test(patchId)) {
throw new Error(
"usage: build-engine-provider-target-host-policy-artifact.mjs " +
"<engine-provider-target-host-policy-YYYYMMDD-NNN>",
);
}
const targetSha256 = Object.freeze({
"nodedc-source/server/routes/n8n.js":
"9bc3638e271102abec91bb80413329befb89d60c0e4dc0548f0dd11e93220d0a",
});
const entries = Object.freeze(Object.keys(targetSha256));
const artifact = join(artifactRoot, `nodedc-${patchId}.tgz`);
await assertFresh(artifact);
await assertExactSources();
const stage = await mkdtemp(join(tmpdir(), "nodedc-engine-provider-target-host-policy-"));
try {
const payload = join(stage, "payload");
for (const relativePath of entries) {
const destination = join(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(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), artifact, stage]);
console.log(JSON.stringify({
ok: true,
patchId,
artifact,
sha256: digest(await readFile(artifact)),
entries,
targetSha256,
services: ["nodedc-backend"],
transition: "exact-provider-literal-target-host",
providerPackage: "gelios.provider.v4",
dataProductId: "fleet.positions.current.v3",
credentialValues: "preserved",
untouched: ["L2 graph", "n8n", "L1", "Engine UI", "databases"],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertExactSources() {
for (const [relativePath, expected] of Object.entries(targetSha256)) {
const sourcePath = join(engineRoot, relativePath);
const info = await lstat(sourcePath);
if (!info.isFile() || info.isSymbolicLink()) {
throw new Error(`engine_provider_target_host_policy_source_unsafe:${relativePath}`);
}
const actual = digest(await readFile(sourcePath));
if (actual !== expected) {
throw new Error(
`engine_provider_target_host_policy_target_mismatch:${relativePath}:` +
`expected=${expected}:actual=${actual}`,
);
}
const source = await readFile(sourcePath, "utf8");
for (const marker of [
"const eligibleHosts = explicitHosts.length",
"allowedHosts: [targetHost]",
"credential_host_not_allowed",
]) {
if (!source.includes(marker)) {
throw new Error(`engine_provider_target_host_policy_marker_missing:${marker}`);
}
}
}
}
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,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) {
throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
}
@@ -24,7 +24,9 @@ const files = [
["packages/external-provider-contract/src/data-product.mjs", "platform/packages/external-provider-contract/src/data-product.mjs"],
["packages/external-provider-contract/src/intake-batch.mjs", "platform/packages/external-provider-contract/src/intake-batch.mjs"],
["packages/external-provider-contract/src/index.mjs", "platform/packages/external-provider-contract/src/index.mjs"],
["packages/external-provider-contract/src/provider-package.mjs", "platform/packages/external-provider-contract/src/provider-package.mjs"],
["packages/external-provider-contract/src/sensitive-field-policy.mjs", "platform/packages/external-provider-contract/src/sensitive-field-policy.mjs"],
["packages/external-provider-contract/providers/gelios", "platform/packages/external-provider-contract/providers/gelios"],
];
const ignoredBasenames = new Set([".DS_Store", ".git", "node_modules"]);
const ignoredDirectoryNames = new Set(["test"]);
@@ -0,0 +1,115 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { cp, 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 platformRoot = resolve(scriptDir, "../..");
const workspaceRoot = resolve(platformRoot, "..");
const foundryRoot = resolve(workspaceRoot, "NODEDC_DESIGN_GUIDELINE");
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
const [patchId = "module-foundry-consumer-policy-v4-20260720-001", ...extra] = process.argv.slice(2);
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) {
throw new Error("patch_id_must_contain_only_letters_digits_dot_underscore_hyphen");
}
const files = [
"registry/data-product-consumer-policies.json",
"scripts/validate-registry.mjs",
"server/foundry-data-product-consumer.mjs",
"server/foundry-data-product-consumer.test.mjs",
];
const stage = await mkdtemp(join(tmpdir(), "nodedc-module-foundry-consumer-policy-artifact-"));
const payload = join(stage, "payload");
const artifact = join(artifactDir, `nodedc-module-foundry-${patchId}.tgz`);
const checksum = `${artifact}.sha256`;
await assertConsumerPolicyBoundary();
try {
await mkdir(payload, { recursive: true });
for (const relativePath of files) {
const source = resolve(foundryRoot, relativePath);
const sourceStat = await lstat(source);
if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
throw new Error(`source_file_rejected:${relativePath}`);
}
const destination = join(payload, relativePath);
await mkdir(dirname(destination), { recursive: true });
await cp(source, destination, { force: true, verbatimSymlinks: true });
}
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=module-foundry\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactDir, { recursive: true });
const tar = spawnSync("python3", ["-c", canonicalTarScript(), artifact, stage], {
encoding: "utf8",
maxBuffer: 32 * 1024 * 1024,
});
if (tar.status !== 0) throw new Error(`tar_failed:${tar.stderr || tar.stdout}`);
const sha256 = createHash("sha256").update(await readFile(artifact)).digest("hex");
await writeFile(checksum, `${sha256} ${artifact.split("/").at(-1)}\n`, "utf8");
console.log(JSON.stringify({ ok: true, patchId, artifact, checksum, sha256, files }, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertConsumerPolicyBoundary() {
const registry = JSON.parse(await readFile(resolve(foundryRoot, files[0]), "utf8"));
if (registry?.schemaVersion !== "nodedc.foundry.data-product-consumer-policies/v1") {
throw new Error("foundry_consumer_policy_registry_invalid");
}
const matches = registry.policies?.filter((policy) => (
policy?.dataProductId === "fleet.positions.current.v4" && policy?.productVersion === "4.0.0"
)) || [];
if (matches.length !== 1) throw new Error("foundry_consumer_policy_v4_missing_or_ambiguous");
const policy = matches[0];
if (
policy.id !== "map-moving-object-current-v4"
|| policy.version !== "4.0.0"
|| policy.staleAfterMs !== null
|| policy.statusContract?.attribute !== "signal_state"
|| JSON.stringify(policy.statusContract?.allowedValues) !== JSON.stringify(["active", "inactive"])
|| policy.statusContract?.missing !== "reject"
|| policy.statusContract?.freshness !== "none"
|| JSON.stringify(policy.terminalStatuses) !== JSON.stringify(["inactive"])
|| policy.removeMode !== "canonical-tombstone-or-snapshot-rebase"
) throw new Error("foundry_consumer_policy_v4_contract_invalid");
const serializedPolicy = JSON.stringify(policy);
if (/(provider|tenant|connection|endpoint|credential|token|secret|authorization)/i.test(serializedPolicy)) {
throw new Error("foundry_consumer_policy_v4_transport_boundary_violation");
}
const consumer = await readFile(resolve(foundryRoot, files[2]), "utf8");
for (const marker of [
"data_product_consumer_fact_status_invalid",
"data_product_consumer_status_field_not_projected",
'statusContract.freshness === "none"',
]) {
if (!consumer.includes(marker)) throw new Error(`foundry_consumer_policy_v4_runtime_guard_missing:${marker}`);
}
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'wb') 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");
}
@@ -0,0 +1,102 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { cp, 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 platformRoot = resolve(scriptDir, "../..");
const workspaceRoot = resolve(platformRoot, "..");
const foundryRoot = resolve(workspaceRoot, "NODEDC_DESIGN_GUIDELINE");
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
const [patchId = "module-foundry-filter-toggle-20260720-001", ...extra] = process.argv.slice(2);
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) {
throw new Error("patch_id_must_contain_only_letters_digits_dot_underscore_hyphen");
}
const files = [
"apps/catalog/src/MapFixturePreview.tsx",
"apps/catalog/src/mapPresentationProfile.ts",
"scripts/map-presentation-filters.test.mjs",
];
const stage = await mkdtemp(join(tmpdir(), "nodedc-module-foundry-filter-toggle-artifact-"));
const payload = join(stage, "payload");
const artifact = join(artifactDir, `nodedc-module-foundry-${patchId}.tgz`);
const checksum = `${artifact}.sha256`;
await assertFilterToggleBoundary();
try {
await mkdir(payload, { recursive: true });
for (const relativePath of files) {
const source = resolve(foundryRoot, relativePath);
const sourceStat = await lstat(source);
if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
throw new Error(`source_file_rejected:${relativePath}`);
}
const destination = join(payload, relativePath);
await mkdir(dirname(destination), { recursive: true });
await cp(source, destination, { force: true, verbatimSymlinks: true });
}
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=module-foundry\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactDir, { recursive: true });
const tar = spawnSync("python3", ["-c", canonicalTarScript(), artifact, stage], {
encoding: "utf8",
maxBuffer: 64 * 1024 * 1024,
});
if (tar.status !== 0) throw new Error(`tar_failed:${tar.stderr || tar.stdout}`);
const sha256 = createHash("sha256").update(await readFile(artifact)).digest("hex");
await writeFile(checksum, `${sha256} ${artifact.split("/").at(-1)}\n`, "utf8");
console.log(JSON.stringify({ ok: true, patchId, artifact, checksum, sha256, files }, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
async function assertFilterToggleBoundary() {
const helper = await readFile(resolve(foundryRoot, files[1]), "utf8");
for (const marker of [
"toggleMapPresentationFacetSelection",
"const { [field]: _removed, ...unconstrained } = facets",
"return unconstrained",
]) {
if (!helper.includes(marker)) throw new Error(`foundry_filter_toggle_helper_missing:${marker}`);
}
const preview = await readFile(resolve(foundryRoot, files[0]), "utf8");
if (!preview.includes("filters: toggleMapPresentationFacetSelection(filters, field, value)")) {
throw new Error("foundry_filter_toggle_component_contract_missing");
}
const test = await readFile(resolve(foundryRoot, files[2]), "utf8");
for (const marker of [
"interactive deselect of the last chip removes the facet constraint",
"interactive deselect preserves other values and facet constraints",
"deselecting the last chip remains empty and never normalizes to all",
]) {
if (!test.includes(marker)) throw new Error(`foundry_filter_toggle_regression_missing:${marker}`);
}
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'wb') 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");
}
@@ -0,0 +1,84 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { cp, lstat, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const platformRoot = resolve(scriptDir, "../..");
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
const [patchId = "ontology-core-20260719-001", ...extra] = process.argv.slice(2);
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) {
throw new Error("usage: build-ontology-core-artifact.mjs [patch-id]");
}
const sourceRoot = resolve(platformRoot, "services/ontology-core");
const destinationRoot = "platform/ontology-core";
const ignoredBasenames = new Set([".DS_Store", ".git", "node_modules", "test"]);
const stage = await mkdtemp(join(tmpdir(), "nodedc-ontology-core-artifact-"));
const payload = join(stage, "payload");
const target = join(artifactDir, `nodedc-platform-${patchId}.tgz`);
try {
await copySafe(sourceRoot, join(payload, destinationRoot));
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=platform\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${destinationRoot}\n`, "utf8");
await mkdir(artifactDir, { recursive: true });
const tar = spawnSync("python3", ["-c", canonicalTarScript(), target, stage], {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
});
if (tar.status !== 0) throw new Error(`tar_failed:${tar.stderr || tar.stdout}`);
console.log(JSON.stringify({
ok: true,
patchId,
artifact: target,
sha256: createHash("sha256").update(await readFile(target)).digest("hex"),
entries: [destinationRoot],
servicesExpected: ["ontology-core", "ai-workspace-hub"],
excluded: [".env*", "node_modules", "test", "secrets"],
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
function canonicalTarScript() {
return [
"import gzip,io,pathlib,sys,tarfile",
"root=pathlib.Path(sys.argv[2])",
"with open(sys.argv[1],'wb') 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");
}
async function copySafe(source, destination) {
const sourceStat = await lstat(source);
if (sourceStat.isSymbolicLink()) throw new Error(`source_symlink_rejected:${relative(platformRoot, source)}`);
if (sourceStat.isFile()) {
await mkdir(dirname(destination), { recursive: true });
await cp(source, destination, { force: true, verbatimSymlinks: true });
return;
}
if (!sourceStat.isDirectory()) throw new Error(`source_type_rejected:${relative(platformRoot, source)}`);
await mkdir(destination, { recursive: true });
for (const entry of await readdir(source, { withFileTypes: true })) {
if (ignoredBasenames.has(entry.name) || entry.name.startsWith(".env")) continue;
const childSource = join(source, entry.name);
const childDestination = join(destination, entry.name);
if (entry.isSymbolicLink()) throw new Error(`source_symlink_rejected:${relative(platformRoot, childSource)}`);
await copySafe(childSource, childDestination);
}
}
@@ -0,0 +1,101 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { cp, 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 here = dirname(fileURLToPath(import.meta.url));
const platformRoot = resolve(here, "../..");
const artifactRoot = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"));
const [transitionId = "20260719-005", ...extra] = process.argv.slice(2);
if (extra.length || !/^\d{8}-[0-9]{3}$/.test(transitionId)) {
throw new Error("usage: build-platform-gelios-provider-v3-artifact.mjs [YYYYMMDD-NNN]");
}
const id = `platform-gelios-provider-v3-${transitionId}`;
const target = join(artifactRoot, `nodedc-${id}.tgz`);
const files = [
"platform/packages/external-provider-contract/providers/gelios/v3/README.md",
"platform/packages/external-provider-contract/providers/gelios/v3/index.mjs",
"platform/packages/external-provider-contract/providers/gelios/v3/package.mjs",
];
const expectedSha256 = new Map([
[files[0], "7ac2318e455786895bebf2e7ee75ae9f86e8958fc5d4699fd0c8c603b8a92ca1"],
[files[1], "dbb82752248fd45c4d3670dadb435123d0575881bfa9458fc0757a421471de24"],
[files[2], "67170084c2d55c3adbed05f1d63c71403689fb59ebc9811e495a55a3c4fa41bf"],
]);
await assertFresh(target);
const stage = await mkdtemp(join(tmpdir(), "nodedc-platform-gelios-provider-v3-"));
const payload = join(stage, "payload");
try {
await mkdir(payload, { recursive: true });
for (const rel of files) {
const source = join(platformRoot, rel.replace(/^platform\//, ""));
const stat = await lstat(source);
if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`source_boundary_invalid:${rel}`);
const bytes = await readFile(source);
if (sha(bytes) !== expectedSha256.get(rel)) throw new Error(`source_sha256_mismatch:${rel}`);
await mkdir(dirname(join(payload, rel)), { recursive: true });
await cp(source, join(payload, rel), { force: false });
}
await writeFile(join(stage, "manifest.env"), `id=${id}\ncomponent=platform\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), target, stage]);
console.log(JSON.stringify({
ok: true,
id,
artifact: target,
artifactSha256: sha(await readFile(target)),
services: [],
providerPackage: "gelios.provider.v3",
dataProductId: "fleet.positions.current.v2",
runtimeEffect: "catalog-only; no service restart",
files,
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
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],'wb') 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 sha(bytes) {
return createHash("sha256").update(bytes).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
return result;
}
@@ -0,0 +1,104 @@
#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { cp, 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 here = dirname(fileURLToPath(import.meta.url));
const platformRoot = resolve(here, "../..");
const artifactRoot = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(here, "../deploy-artifacts"));
const [transitionId = "20260720-001", ...extra] = process.argv.slice(2);
if (extra.length || !/^\d{8}-[0-9]{3}$/.test(transitionId)) {
throw new Error("usage: build-platform-gelios-provider-v4-artifact.mjs [YYYYMMDD-NNN]");
}
const id = `platform-gelios-provider-v4-${transitionId}`;
const target = join(artifactRoot, `nodedc-${id}.tgz`);
const files = [
"platform/packages/external-provider-contract/src/provider-package.mjs",
"platform/packages/external-provider-contract/providers/gelios/v4/README.md",
"platform/packages/external-provider-contract/providers/gelios/v4/index.mjs",
"platform/packages/external-provider-contract/providers/gelios/v4/package.mjs",
"platform/services/external-data-plane/definitions/fleet.positions.current.v3.json",
];
const expectedSha256 = new Map([
[files[0], "8ae73cae0be8cbf8484125e1ccf836fdc245b31872a5c7888ced289ed1895ba2"],
[files[1], "9f38f5cb267269b54053fa590a3970abb4b6b9803fc931e997be4293aa6e592a"],
[files[2], "b92fb1fed6ff2fe29c3dc77978e7c35dcdf4c7f2af4ae63ada23e9c3119e7fd9"],
[files[3], "55a46f825e12bcef2354fefd956e674b72fea68b6997df3fcbe89b0a074ec9b8"],
[files[4], "04d458f050313468990849f60d37a8a6c9aadd355137d4084b66556bb4a4b673"],
]);
await assertFresh(target);
const stage = await mkdtemp(join(tmpdir(), "nodedc-platform-gelios-provider-v4-"));
const payload = join(stage, "payload");
try {
await mkdir(payload, { recursive: true });
for (const rel of files) {
const source = join(platformRoot, rel.replace(/^platform\//, ""));
const stat = await lstat(source);
if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`source_boundary_invalid:${rel}`);
const bytes = await readFile(source);
if (sha(bytes) !== expectedSha256.get(rel)) throw new Error(`source_sha256_mismatch:${rel}`);
await mkdir(dirname(join(payload, rel)), { recursive: true });
await cp(source, join(payload, rel), { force: false });
}
await writeFile(join(stage, "manifest.env"), `id=${id}\ncomponent=platform\ntype=app-overlay\n`, "utf8");
await writeFile(join(stage, "files.txt"), `${files.join("\n")}\n`, "utf8");
await mkdir(artifactRoot, { recursive: true });
run("python3", ["-c", canonicalTarScript(), target, stage]);
console.log(JSON.stringify({
ok: true,
id,
artifact: target,
artifactSha256: sha(await readFile(target)),
services: ["external-data-plane"],
ontologyPackage: "gelios@1.1.0",
providerPackage: "gelios.provider.v4",
dataProductId: "fleet.positions.current.v3",
files,
}, null, 2));
} finally {
await rm(stage, { recursive: true, force: true });
}
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],'wb') 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 sha(bytes) {
return createHash("sha256").update(bytes).digest("hex");
}
function run(command, args) {
const result = spawnSync(command, args, {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
stdio: ["ignore", "pipe", "pipe"],
});
if (result.status !== 0) throw new Error(`${command}_failed:${result.stderr || result.stdout}`);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,157 @@
import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-composite-provider-v4-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-composite-provider-v4-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_composite_provider_v4",
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 EngineCompositeProviderV4Test(unittest.TestCase):
def test_predecessor_map_matches_the_applied_release_order(self):
self.assertEqual(
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256,
{
"nodedc-source/server/assets/provider-packages/v1/catalog.json":
"992159fc457ec76ce1f45aad337604c8a72b29252d44fbccda515f0fd6ea6428",
"nodedc-source/server/dataProductPublishGrant/providerCatalog.js":
"901b8fad80018ce177b34ced804b39cb140a47e831414057f484296b373c651d",
"nodedc-source/server/dataProductPublishGrant/service.js":
"6a417b25b080c05b40c771df4e2dca163491af2c9083ff73dc7e54ad3b360241",
"nodedc-source/server/dataProductPublishGrant/store.js":
"a92303b2732e21f68c1ac732fa26e4983cbadf3515741cee983b916a283d754c",
},
)
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_is_deterministic_and_emits_exact_backend_only_slice(self):
current_sha256 = {
relative_path: hashlib.sha256((ENGINE_ROOT / relative_path).read_bytes()).hexdigest()
for relative_path in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES
}
if current_sha256 != RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256:
self.skipTest("historical v4 builder source has advanced to its exact successor")
with tempfile.TemporaryDirectory(prefix="nodedc-engine-composite-v4-") 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["credentialValues"], "preserved")
self.assertEqual(
tuple(first["entries"]),
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES,
)
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()
)
payload = extract / "payload"
self.assertTrue(RUNNER.is_engine_composite_provider_v4_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_composite_provider_v4_slice(payload, entries)
for relative_path, expected in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256.items():
self.assertEqual(
hashlib.sha256((payload / relative_path).read_bytes()).hexdigest(),
expected,
)
def test_preflight_requires_every_exact_predecessor_and_immutable_backend(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-composite-v4-preflight-") as directory:
root = Path(directory)
for relative_path in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
def exact_sha(path):
relative_path = Path(path).relative_to(root).as_posix()
return RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_sha),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_composite_provider_v4_predecessor()
self.assertEqual(result["mode"], "exact-composite-provider-v3-to-v4")
self.assertEqual(
result["predecessor_sha256"],
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256,
)
self.assertEqual(
result["target_sha256"],
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256,
)
drift_path = root / RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES[1]
def drift_sha(path):
if Path(path) == drift_path:
return "0" * 64
return exact_sha(path)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=drift_sha),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_composite_provider_v4_predecessor()
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -0,0 +1,153 @@
#!/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)
@@ -13,6 +13,7 @@ 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"
ENGINE_BUILDER = SCRIPT_DIR / "build-engine-mcp-ontology-sdk-artifact.mjs"
PLATFORM_BUILDER = SCRIPT_DIR / "build-platform-gelios-provider-v2-artifact.mjs"
@@ -53,6 +54,12 @@ class EngineMcpOntologySdkTest(unittest.TestCase):
self.assertFalse(Path(member.name).name.startswith("._"))
def test_engine_builder_is_byte_reproducible(self):
current_sha256 = {
relative_path: hashlib.sha256((ENGINE_ROOT / relative_path).read_bytes()).hexdigest()
for relative_path in RUNNER.ENGINE_MCP_ONTOLOGY_SDK_TARGET_SHA256
}
if current_sha256 != RUNNER.ENGINE_MCP_ONTOLOGY_SDK_TARGET_SHA256:
self.skipTest("historical Ontology/SDK builder source has advanced to its exact successor")
outputs = []
with tempfile.TemporaryDirectory(prefix="nodedc-engine-mcp-ontology-sdk-") as directory:
for index in range(2):
@@ -0,0 +1,145 @@
import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-provider-authority-diagnostics-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-provider-authority-diagnostics-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_provider_authority_diagnostics",
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 EngineProviderAuthorityDiagnosticsTest(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_one_file_slice(self):
with tempfile.TemporaryDirectory(prefix="nodedc-provider-authority-") 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(
tuple(first["entries"]),
RUNNER.ENGINE_PROVIDER_AUTHORITY_DIAGNOSTICS_ARTIFACT_ENTRIES,
)
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())
payload = extract / "payload"
self.assertTrue(RUNNER.is_engine_provider_authority_diagnostics_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_provider_authority_diagnostics_slice(payload, entries)
def test_preflight_requires_the_exact_deployed_predecessor(self):
with tempfile.TemporaryDirectory(prefix="nodedc-provider-authority-preflight-") as directory:
root = Path(directory)
relative_path = RUNNER.ENGINE_PROVIDER_AUTHORITY_DIAGNOSTICS_ARTIFACT_ENTRIES[0]
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
expected = RUNNER.ENGINE_PROVIDER_AUTHORITY_DIAGNOSTICS_PREDECESSOR_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=expected),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_provider_authority_diagnostics_predecessor()
self.assertEqual(result["mode"], "exact-provider-authority-reason-codes")
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value="0" * 64),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_provider_authority_diagnostics_predecessor()
def test_healthchecks_dispatch_authority_diagnostics_acceptance(self):
entries = RUNNER.ENGINE_PROVIDER_AUTHORITY_DIAGNOSTICS_ARTIFACT_ENTRIES
root = Path("/engine")
target_hash = next(iter(RUNNER.ENGINE_PROVIDER_AUTHORITY_DIAGNOSTICS_TARGET_SHA256.values()))
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=target_hash),
mock.patch.object(RUNNER, "healthcheck_compose_service"),
mock.patch.object(RUNNER, "component_healthchecks", return_value=()),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(
RUNNER,
"accept_engine_provider_authority_diagnostics_runtime",
return_value={"live": "accepted"},
) as acceptance,
mock.patch.object(RUNNER, "healthcheck_container"),
):
RUNNER.run_healthchecks("engine", entries, ("nodedc-backend",))
acceptance.assert_called_once_with()
def test_live_acceptance_uses_exact_reason_code_contract(self):
expected_live = "engine-provider-authority-diagnostics:exact-reason-codes:v1"
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_provider_authority_diagnostics_runtime()
self.assertEqual(result["live"], expected_live)
self.assertEqual(backend_probe.call_args.args[1], "Engine provider authority diagnostics")
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -0,0 +1,193 @@
import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-provider-rotating-slot-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-provider-rotating-slot-20991231-999"
AUTHORITY_SUCCESSOR_SHA256 = "1a14299167ebe17efd677fa3c59b84c80e12d6846bac6f40f9bcae0729ab22c6"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_provider_rotating_slot",
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 EngineProviderRotatingSlotTest(unittest.TestCase):
def source_has_exact_successor(self):
path = ENGINE_ROOT / "nodedc-source/server/dataProductPublishGrant/providerCatalog.js"
return hashlib.sha256(path.read_bytes()).hexdigest() == AUTHORITY_SUCCESSOR_SHA256
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_two_file_slice(self):
if self.source_has_exact_successor():
self.skipTest("historical rotating-slot builder source has advanced to its exact successor")
with tempfile.TemporaryDirectory(prefix="nodedc-provider-rotating-slot-") 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["credentialSlot"], "ndcProviderRotatingAccessApi")
self.assertEqual(
tuple(first["entries"]),
RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_ARTIFACT_ENTRIES,
)
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()
)
payload = extract / "payload"
self.assertTrue(RUNNER.is_engine_provider_rotating_slot_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_provider_rotating_slot_slice(payload, entries)
def test_preflight_is_exact_and_rejects_any_drift(self):
with tempfile.TemporaryDirectory(prefix="nodedc-provider-rotating-preflight-") as directory:
root = Path(directory)
for relative_path in RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_ARTIFACT_ENTRIES:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
def exact_sha(path):
relative_path = Path(path).relative_to(root).as_posix()
return RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_PREDECESSOR_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_sha),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_provider_rotating_slot_predecessor()
self.assertEqual(result["mode"], "exact-gelios-v4-credential-slot-alignment")
self.assertEqual(
result["predecessor_sha256"],
RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_PREDECESSOR_SHA256,
)
drift_path = root / RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_ARTIFACT_ENTRIES[0]
def drift_sha(path):
if Path(path) == drift_path:
return "0" * 64
return exact_sha(path)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=drift_sha),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_provider_rotating_slot_predecessor()
def test_healthchecks_dispatch_exact_rotating_slot_acceptance(self):
entries = RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_ARTIFACT_ENTRIES
root = Path("/engine")
def installed_sha(path):
relative_path = Path(path).relative_to(root).as_posix()
return RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_TARGET_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=installed_sha),
mock.patch.object(RUNNER, "healthcheck_compose_service"),
mock.patch.object(RUNNER, "component_healthchecks", return_value=()),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(
RUNNER,
"accept_engine_provider_rotating_slot_runtime",
return_value={"live": "accepted"},
) as rotating_acceptance,
mock.patch.object(RUNNER, "accept_engine_composite_provider_runtime") as composite_acceptance,
mock.patch.object(RUNNER, "healthcheck_container"),
):
RUNNER.run_healthchecks("engine", entries, ("nodedc-backend",))
rotating_acceptance.assert_called_once_with()
composite_acceptance.assert_not_called()
def test_live_acceptance_uses_the_rotating_slot_target_contract(self):
if self.source_has_exact_successor():
self.skipTest("historical rotating-slot live fixture source has advanced to its exact successor")
expected_live = (
"engine-provider-rotating-slot:gelios.provider.v4:"
"ndcProviderRotatingAccessApi:fleet.positions.current.v3:monitoring,units"
)
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_provider_rotating_slot_runtime()
self.assertEqual(result["live"], expected_live)
self.assertEqual(
result["target_sha256"],
RUNNER.ENGINE_PROVIDER_ROTATING_SLOT_TARGET_SHA256,
)
self.assertEqual(
backend_probe.call_args.args[1],
"Engine provider rotating slot authority",
)
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -0,0 +1,90 @@
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-provider-security-catalog-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
CATALOG_REL = "nodedc-source/server/assets/provider-packages/v1/catalog.json"
def load_runner():
loader = importlib.machinery.SourceFileLoader("nodedc_engine_provider_catalog", 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 EngineProviderSecurityCatalogTest(unittest.TestCase):
def test_builder_emits_exact_backend_only_slice(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-provider-catalog-") as directory:
artifact_dir = Path(directory) / "artifacts"
env = os.environ.copy()
env["NODEDC_ENGINE_SOURCE_ROOT"] = str(ENGINE_ROOT)
env["NODEDC_DEPLOY_ARTIFACT_DIR"] = str(artifact_dir)
completed = subprocess.run(
["node", str(BUILDER_PATH), "20991231-999"],
check=True,
capture_output=True,
text=True,
env=env,
)
result = json.loads(completed.stdout)
artifact = Path(result["artifact"])
self.assertEqual(result["services"], ["nodedc-backend"])
with tarfile.open(artifact, "r:gz") as archive:
archive.extractall(Path(directory) / "extract", filter="data")
root = Path(directory) / "extract"
entries = tuple((root / "files.txt").read_text(encoding="utf-8").splitlines())
payload = root / "payload"
self.assertTrue(RUNNER.is_engine_provider_security_catalog_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
catalog = RUNNER.validate_engine_provider_security_catalog_payload(payload, entries)
self.assertEqual(catalog["packages"][0]["id"], "gelios.provider.v3")
def test_preflight_requires_exact_v1_predecessor_and_immutable_backend(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-provider-predecessor-") as directory:
root = Path(directory)
target = root / CATALOG_REL
target.parent.mkdir(parents=True)
source = subprocess.run(
["git", "show", "HEAD:nodedc-source/server/assets/provider-packages/v1/catalog.json"],
cwd=ENGINE_ROOT,
check=True,
capture_output=True,
).stdout
target.write_bytes(source)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_provider_security_catalog_predecessor()
self.assertEqual(
result["catalog_sha256"],
RUNNER.ENGINE_PROVIDER_SECURITY_CATALOG_PREDECESSOR_SHA256,
)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,145 @@
import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-provider-target-host-policy-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-provider-target-host-policy-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_provider_target_host_policy",
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 EngineProviderTargetHostPolicyTest(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_one_file_slice(self):
with tempfile.TemporaryDirectory(prefix="nodedc-provider-target-host-") 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(
tuple(first["entries"]),
RUNNER.ENGINE_PROVIDER_TARGET_HOST_POLICY_ARTIFACT_ENTRIES,
)
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())
payload = extract / "payload"
self.assertTrue(RUNNER.is_engine_provider_target_host_policy_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_provider_target_host_policy_slice(payload, entries)
def test_preflight_requires_the_exact_deployed_predecessor(self):
with tempfile.TemporaryDirectory(prefix="nodedc-provider-target-host-preflight-") as directory:
root = Path(directory)
relative_path = RUNNER.ENGINE_PROVIDER_TARGET_HOST_POLICY_ARTIFACT_ENTRIES[0]
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
expected = RUNNER.ENGINE_PROVIDER_TARGET_HOST_POLICY_PREDECESSOR_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=expected),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_provider_target_host_policy_predecessor()
self.assertEqual(result["mode"], "exact-provider-literal-target-host")
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value="0" * 64),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_provider_target_host_policy_predecessor()
def test_healthchecks_dispatch_target_host_policy_acceptance(self):
entries = RUNNER.ENGINE_PROVIDER_TARGET_HOST_POLICY_ARTIFACT_ENTRIES
root = Path("/engine")
target_hash = next(iter(RUNNER.ENGINE_PROVIDER_TARGET_HOST_POLICY_TARGET_SHA256.values()))
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", return_value=target_hash),
mock.patch.object(RUNNER, "healthcheck_compose_service"),
mock.patch.object(RUNNER, "component_healthchecks", return_value=()),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
mock.patch.object(
RUNNER,
"accept_engine_provider_target_host_policy_runtime",
return_value={"live": "accepted"},
) as acceptance,
mock.patch.object(RUNNER, "healthcheck_container"),
):
RUNNER.run_healthchecks("engine", entries, ("nodedc-backend",))
acceptance.assert_called_once_with()
def test_live_acceptance_uses_exact_literal_host_contract(self):
expected_live = "engine-provider-target-host-policy:exact-literal-host:v1"
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_provider_target_host_policy_runtime()
self.assertEqual(result["live"], expected_live)
self.assertEqual(backend_probe.call_args.args[1], "Engine provider target host policy")
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -11,6 +11,10 @@ from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
BUILDER = SCRIPT_DIR / "build-engine-data-product-publish-grant-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
HISTORICAL_PROVIDER_CATALOG_SHA256 = (
"9c931f9abfcadb5b34a8a854c2efb8fd79913e000eecf0967d1b7c500bf9a56a"
)
EXPECTED_ENTRIES = [
"nodedc-source/server/assets/provider-packages/v1/catalog.json",
"nodedc-source/server/dataProductPublishGrant",
@@ -26,6 +30,13 @@ SUCCESSFUL_CREDENTIAL_SINK_INDEX_SHA256 = (
class EnginePublishGrantArtifactTest(unittest.TestCase):
def historical_source_is_current(self):
catalog = (
ENGINE_ROOT
/ "nodedc-source/server/assets/provider-packages/v1/catalog.json"
)
return hashlib.sha256(catalog.read_bytes()).hexdigest() == HISTORICAL_PROVIDER_CATALOG_SHA256
def build(self, artifact_dir, patch_id):
environment = os.environ.copy()
environment["NODEDC_DEPLOY_ARTIFACT_DIR"] = str(artifact_dir)
@@ -39,6 +50,8 @@ class EnginePublishGrantArtifactTest(unittest.TestCase):
return json.loads(result.stdout)
def test_artifact_is_narrow_secret_free_and_deterministic(self):
if not self.historical_source_is_current():
self.skipTest("historical Publish-grant builder source has advanced to its exact successor")
with tempfile.TemporaryDirectory(prefix="nodedc-engine-publish-artifact-") as directory:
root = Path(directory)
first_dir = root / "first"
@@ -70,6 +83,18 @@ class EnginePublishGrantArtifactTest(unittest.TestCase):
"payload/nodedc-source/services/backend/data-product-publish-grant/"
"docker-compose.immutable-runtime.yml"
).read().decode("utf-8")
catalog = json.loads(archive.extractfile(
"payload/nodedc-source/server/assets/provider-packages/v1/catalog.json"
).read())
provider_catalog_source = archive.extractfile(
"payload/nodedc-source/server/dataProductPublishGrant/providerCatalog.js"
).read().decode("utf-8")
service_source = archive.extractfile(
"payload/nodedc-source/server/dataProductPublishGrant/service.js"
).read().decode("utf-8")
store_source = archive.extractfile(
"payload/nodedc-source/server/dataProductPublishGrant/store.js"
).read().decode("utf-8")
self.assertEqual(files, EXPECTED_ENTRIES)
self.assertEqual(
@@ -115,6 +140,29 @@ class EnginePublishGrantArtifactTest(unittest.TestCase):
)
self.assertIn("read_only: true", runtime_override)
self.assertEqual(runtime_override.count("create_host_path: false"), 2)
provider = catalog["packages"][0]
self.assertEqual(first["providerPackage"], "gelios.provider.v4")
self.assertEqual(first["dataProductId"], "fleet.positions.current.v3")
self.assertEqual(first["credentialValues"], "preserved")
self.assertEqual(provider["id"], "gelios.provider.v4")
self.assertEqual(
[capability["id"] for capability in provider["capabilities"]],
[
"gelios.monitoring_config.current.read",
"gelios.units.current.read",
],
)
self.assertEqual(
[capability["request"]["url"] for capability in provider["capabilities"]],
[
"https://api.geliospro.com/api/v1/users/me/monitoring-config",
"https://api.geliospro.com/api/v1/units?incltrip=true",
],
)
self.assertIn("function capabilityRequests(capability)", provider_catalog_source)
self.assertIn("exactHttpRequestUrl(n8n)", provider_catalog_source)
self.assertIn("providerRequestNodeIds", service_source)
self.assertIn("providerRequestNodeIds", store_source)
def test_builder_requires_a_fresh_never_issued_patch_id(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-publish-id-") as directory:
@@ -140,6 +188,8 @@ class EnginePublishGrantArtifactTest(unittest.TestCase):
self.assertNotEqual(result.returncode, 0)
self.assertIn(expected, result.stderr)
if not self.historical_source_is_current():
return
self.build(artifact_dir, PATCH_ID)
duplicate = subprocess.run(
["node", str(BUILDER), PATCH_ID],
@@ -20,7 +20,9 @@ EXPECTED_ENTRIES = [
"platform/packages/external-provider-contract/src/data-product.mjs",
"platform/packages/external-provider-contract/src/intake-batch.mjs",
"platform/packages/external-provider-contract/src/index.mjs",
"platform/packages/external-provider-contract/src/provider-package.mjs",
"platform/packages/external-provider-contract/src/sensitive-field-policy.mjs",
"platform/packages/external-provider-contract/providers/gelios",
]
@@ -0,0 +1,103 @@
#!/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
BUILDER = SCRIPT_DIR / "build-module-foundry-consumer-policy-artifact.mjs"
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
PATCH_ID = "module-foundry-consumer-policy-v4-unit-001"
EXPECTED_FILES = (
"registry/data-product-consumer-policies.json",
"scripts/validate-registry.mjs",
"server/foundry-data-product-consumer.mjs",
"server/foundry-data-product-consumer.test.mjs",
)
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_module_foundry_consumer_policy_artifact",
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 ModuleFoundryConsumerPolicyArtifactTest(unittest.TestCase):
def build(self, artifact_dir):
environment = os.environ.copy()
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_builder_is_deterministic_exact_scope_and_runner_compatible(self):
with tempfile.TemporaryDirectory(prefix="nodedc-foundry-policy-v4-") 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(tuple(first["files"]), EXPECTED_FILES)
extracted = root / "loaded"
extracted.mkdir()
manifest, entries, payload = RUNNER.load_artifact(first_artifact, extracted)
self.assertEqual(manifest["component"], "module-foundry")
self.assertEqual(tuple(entries), EXPECTED_FILES)
self.assertEqual(RUNNER.component_services("module-foundry", entries), ("nodedc-module-foundry",))
registry = json.loads((payload / EXPECTED_FILES[0]).read_text(encoding="utf-8"))
policies = [
policy for policy in registry["policies"]
if policy["dataProductId"] == "fleet.positions.current.v4"
and policy["productVersion"] == "4.0.0"
]
self.assertEqual(len(policies), 1)
policy = policies[0]
self.assertEqual(policy["id"], "map-moving-object-current-v4")
self.assertEqual(policy["statusContract"]["attribute"], "signal_state")
self.assertEqual(policy["statusContract"]["allowedValues"], ["active", "inactive"])
self.assertEqual(policy["statusContract"]["freshness"], "none")
self.assertIsNone(policy["staleAfterMs"])
with tarfile.open(first_artifact, "r:gz") as archive:
members = archive.getmembers()
names = [member.name for member in members]
regular_payloads = [
archive.extractfile(member).read()
for member in members
if member.isfile()
]
self.assertFalse(any(Path(name).name.startswith("._") for name in names))
self.assertFalse(any("/.git/" in name or "/node_modules/" in name or "/runtime-data/" in name for name in names))
self.assertNotIn(b"-----BEGIN PRIVATE KEY-----", b"\n".join(regular_payloads))
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -0,0 +1,96 @@
#!/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
BUILDER = SCRIPT_DIR / "build-module-foundry-filter-toggle-artifact.mjs"
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
PATCH_ID = "module-foundry-filter-toggle-unit-001"
EXPECTED_FILES = (
"apps/catalog/src/MapFixturePreview.tsx",
"apps/catalog/src/mapPresentationProfile.ts",
"scripts/map-presentation-filters.test.mjs",
)
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_module_foundry_filter_toggle_artifact",
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 ModuleFoundryFilterToggleArtifactTest(unittest.TestCase):
def build(self, artifact_dir):
environment = os.environ.copy()
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_builder_is_deterministic_exact_scope_and_runner_compatible(self):
with tempfile.TemporaryDirectory(prefix="nodedc-foundry-filter-toggle-") 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(tuple(first["files"]), EXPECTED_FILES)
extracted = root / "loaded"
extracted.mkdir()
manifest, entries, payload = RUNNER.load_artifact(first_artifact, extracted)
self.assertEqual(manifest["component"], "module-foundry")
self.assertEqual(tuple(entries), EXPECTED_FILES)
self.assertEqual(RUNNER.component_services("module-foundry", entries), ("nodedc-module-foundry",))
helper = (payload / EXPECTED_FILES[1]).read_text(encoding="utf-8")
preview = (payload / EXPECTED_FILES[0]).read_text(encoding="utf-8")
regression = (payload / EXPECTED_FILES[2]).read_text(encoding="utf-8")
self.assertIn("toggleMapPresentationFacetSelection", helper)
self.assertIn("return unconstrained", helper)
self.assertIn("filters: toggleMapPresentationFacetSelection(filters, field, value)", preview)
self.assertIn("interactive deselect of the last chip removes the facet constraint", regression)
with tarfile.open(first_artifact, "r:gz") as archive:
members = archive.getmembers()
names = [member.name for member in members]
regular_payloads = [
archive.extractfile(member).read()
for member in members
if member.isfile()
]
self.assertFalse(any(Path(name).name.startswith("._") for name in names))
self.assertFalse(any("/.git/" in name or "/node_modules/" in name or "/runtime-data/" in name for name in names))
self.assertNotIn(b"-----BEGIN PRIVATE KEY-----", b"\n".join(regular_payloads))
if __name__ == "__main__":
unittest.main(verbosity=2)
@@ -372,8 +372,10 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
original_root = RUNNER.COMPONENTS["engine"]["payload_root"]
original_hashes = RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256
original_installed_hashes = RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256
RUNNER.COMPONENTS["engine"]["payload_root"] = root
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256 = expected
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256 = expected
try:
self.assertEqual(
RUNNER.preflight_engine_data_product_publish_grant_predecessor(),
@@ -391,6 +393,7 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
RUNNER.preflight_engine_data_product_publish_grant_predecessor()
finally:
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256 = original_hashes
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256 = original_installed_hashes
RUNNER.COMPONENTS["engine"]["payload_root"] = original_root
def test_installed_publish_update_preserves_foundation_and_allows_only_grant_source_changes(self):
@@ -441,8 +444,10 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
original_root = RUNNER.COMPONENTS["engine"]["payload_root"]
original_hashes = RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256
original_installed_hashes = RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256
RUNNER.COMPONENTS["engine"]["payload_root"] = root
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256 = expected
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256 = expected
try:
self.assertEqual(
RUNNER.preflight_engine_data_product_publish_grant_predecessor(payload),
@@ -470,6 +475,99 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
RUNNER.preflight_engine_data_product_publish_grant_predecessor(payload)
finally:
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_PREDECESSOR_SHA256 = original_hashes
RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_INSTALLED_FOUNDATION_SHA256 = original_installed_hashes
RUNNER.COMPONENTS["engine"]["payload_root"] = original_root
def test_composite_provider_update_requires_exact_v3_to_v4_catalog_and_four_paths(self):
engine_source = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
current_target_sha256 = {
rel: hashlib.sha256((engine_source / rel).read_bytes()).hexdigest()
for rel in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES
}
if current_target_sha256 != RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256:
self.skipTest("historical v3-to-v4 fixture source has advanced to its exact successor")
with tempfile.TemporaryDirectory(prefix="nodedc-composite-provider-update-") as directory:
base = Path(directory)
root = base / "installed"
payload = base / "payload"
root.mkdir()
payload.mkdir()
v3_catalog = {
"schemaVersion": "nodedc.engine.provider-security-catalog/v1",
"packages": [{
"id": "gelios.provider.v3",
"version": "3.0.0",
"providerId": "gelios",
"providerCredential": {
"authModeId": "gelios.rest-rotating-bearer.v3",
"credentialType": "httpBearerAuth",
},
"capabilities": [{
"id": "gelios.units.current.read",
"classification": "read",
"status": "implemented",
"request": {
"method": "GET",
"url": "https://api.geliospro.com/api/v1/units",
},
"dataProductIds": ["fleet.positions.current.v2"],
}],
"publisher": {
"nodeType": "n8n-nodes-ndc.ndcDataProductPublish",
"credentialType": "ndcDataProductWriterApi",
},
}],
}
installed_catalog = f"{json.dumps(v3_catalog, indent=2)}\n"
self.assertEqual(
hashlib.sha256(installed_catalog.encode()).hexdigest(),
RUNNER.ENGINE_PUBLISH_GRANT_COMPOSITE_PROVIDER_CATALOG_PREDECESSOR_SHA256,
)
for rel in RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_ARTIFACT_ENTRIES:
if rel == "nodedc-source/server/dataProductPublishGrant":
continue
for destination in (root, payload):
path = destination / rel
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(f"shared:{rel}\n", encoding="utf-8")
for name in RUNNER.ENGINE_DATA_PRODUCT_PUBLISH_GRANT_SOURCE_FILES:
rel = f"nodedc-source/server/dataProductPublishGrant/{name}"
for destination in (root, payload):
path = destination / rel
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(f"installed:{name}\n", encoding="utf-8")
catalog_rel = RUNNER.ENGINE_PROVIDER_SECURITY_CATALOG_REL
(root / catalog_rel).write_text(installed_catalog, encoding="utf-8")
for rel in RUNNER.ENGINE_PUBLISH_GRANT_COMPOSITE_PROVIDER_CHANGED_PATHS:
source = engine_source / rel
(payload / rel).write_bytes(source.read_bytes())
original_root = RUNNER.COMPONENTS["engine"]["payload_root"]
RUNNER.COMPONENTS["engine"]["payload_root"] = root
try:
with mock.patch.object(
RUNNER,
"validate_installed_engine_data_product_publish_grant_foundation",
return_value="compose-sha256",
):
self.assertEqual(
RUNNER.preflight_engine_data_product_publish_grant_predecessor(payload),
{
"mode": "installed-composite-provider-update",
"compose_sha256": "compose-sha256",
"changed_paths": RUNNER.ENGINE_PUBLISH_GRANT_COMPOSITE_PROVIDER_CHANGED_PATHS,
},
)
(root / catalog_rel).write_text("{}\n", encoding="utf-8")
with self.assertRaisesRegex(
RUNNER.DeployError,
"composite provider catalog transition mismatch",
):
RUNNER.preflight_engine_data_product_publish_grant_predecessor(payload)
finally:
RUNNER.COMPONENTS["engine"]["payload_root"] = original_root
def test_edp_healthcheck_requires_database_and_managed_provisioning(self):