fix: Remove agent harness checksum validation (no-changelog) (#38776)

This commit is contained in:
Declan Carroll
2026-09-16 07:17:17 +00:00
committed by GitHub
parent 706183b79e
commit c09e00884c
3 changed files with 15 additions and 30 deletions
+1 -2
View File
@@ -2,6 +2,5 @@
"repository": "n8n-io/cat-bot",
"releaseTag": "harness-v0.3.0",
"version": "0.3.0",
"assetName": "n8n-opencode-harness-0.3.0.tgz",
"sha256": "e1ff2d17291b7f9fb16c7238d23af3d6dc59fc0fe60639ef9e7d1035f21f0fe9"
"assetName": "n8n-opencode-harness-0.3.0.tgz"
}
+2 -11
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env node
import { execFileSync } from 'node:child_process';
import { createHash } from 'node:crypto';
import {
existsSync,
lstatSync,
@@ -25,8 +24,7 @@ export function validateLock(lock) {
lock?.repository !== REPOSITORY ||
!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(lock.version) ||
lock.releaseTag !== `harness-v${lock.version}` ||
lock.assetName !== `n8n-opencode-harness-${lock.version}.tgz` ||
!/^[0-9a-f]{64}$/.test(lock.sha256)
lock.assetName !== `n8n-opencode-harness-${lock.version}.tgz`
) {
throw new Error('The agent harness lock is invalid.');
}
@@ -41,10 +39,6 @@ export function readLock(lockPath = join(REPO_ROOT, 'agent-harness.lock.json'))
}
}
export function sha256File(path) {
return createHash('sha256').update(readFileSync(path)).digest('hex');
}
export function downloadReleaseAsset(lock, destination, { run = execFileSync } = {}) {
try {
run(
@@ -99,7 +93,7 @@ export function installAgentHarness({
const pluginPath = join(bundlePath, 'plugins', PLUGIN_FILE);
mkdirSync(cacheRoot, { recursive: true });
// The version cache is write-once and trusted after its checksum succeeds.
// The version cache is write-once after a successful installation.
const cacheHit = existsSync(pluginPath);
if (!cacheHit) {
const stagingRoot = mkdtempSync(join(cacheRoot, '.install-'));
@@ -108,9 +102,6 @@ export function installAgentHarness({
try {
mkdirSync(stagedVersion);
download(lock, stagedVersion);
if (sha256File(archivePath) !== lock.sha256) {
throw new Error('Agent harness checksum mismatch.');
}
// Cat-bot validates archive contents before publishing these pinned bytes.
extract(archivePath, stagedVersion);
if (!existsSync(join(stagedVersion, BUNDLE_ROOT, 'plugins', PLUGIN_FILE))) {
+12 -17
View File
@@ -15,12 +15,7 @@ import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
import { afterEach, test } from 'node:test';
import {
downloadReleaseAsset,
installAgentHarness,
sha256File,
validateLock,
} from './agent-harness.mjs';
import { downloadReleaseAsset, installAgentHarness, validateLock } from './agent-harness.mjs';
const temporaryDirectories = [];
@@ -46,14 +41,13 @@ function makeAsset(root, version = '1.2.3') {
return asset;
}
function writeLock(root, asset, overrides = {}) {
function writeLock(root, overrides = {}) {
const version = '1.2.3';
const lock = {
repository: 'n8n-io/cat-bot',
releaseTag: `harness-v${version}`,
version,
assetName: `n8n-opencode-harness-${version}.tgz`,
sha256: sha256File(asset),
...overrides,
};
const lockPath = join(root, 'agent-harness.lock.json');
@@ -78,7 +72,6 @@ test('validates the pinned release values', () => {
releaseTag: 'harness-v1.2.3',
version: '1.2.3',
assetName: 'n8n-opencode-harness-1.2.3.tgz',
sha256: 'a'.repeat(64),
};
assert.equal(validateLock(lock), lock);
for (const invalid of [
@@ -86,18 +79,17 @@ test('validates the pinned release values', () => {
{ releaseTag: 'latest' },
{ version: '../outside' },
{ assetName: 'other.tgz' },
{ sha256: 'invalid' },
]) {
assert.throws(() => validateLock({ ...lock, ...invalid }), /lock is invalid/);
}
});
test('installs the verified release and activates its plugin', () => {
test('installs the pinned release and activates its plugin', () => {
const root = fixtureDirectory();
const asset = makeAsset(root);
const result = installAgentHarness({
...installerPaths(root),
lockPath: writeLock(root, asset),
lockPath: writeLock(root),
download: copyAsset(asset),
});
@@ -115,7 +107,7 @@ test('reuses an installed release without downloading it again', () => {
const asset = makeAsset(root);
const options = {
...installerPaths(root),
lockPath: writeLock(root, asset),
lockPath: writeLock(root),
download: copyAsset(asset),
};
installAgentHarness(options);
@@ -127,7 +119,7 @@ test('reuses an installed release without downloading it again', () => {
assert.equal(result.cacheHit, true);
});
test('keeps the active plugin when verification fails', () => {
test('keeps the active plugin when installation fails', () => {
const root = fixtureDirectory();
const asset = makeAsset(root);
const paths = installerPaths(root);
@@ -140,10 +132,13 @@ test('keeps the active plugin when verification fails', () => {
() =>
installAgentHarness({
...paths,
lockPath: writeLock(root, asset, { sha256: '0'.repeat(64) }),
lockPath: writeLock(root),
download: copyAsset(asset),
extract: () => {
throw new Error('extraction failed');
},
}),
/checksum mismatch/,
/extraction failed/,
);
assert.equal(readlinkSync(paths.pluginLink), previous);
});
@@ -159,7 +154,7 @@ test('does not overwrite a user plugin file', () => {
() =>
installAgentHarness({
...paths,
lockPath: writeLock(root, asset),
lockPath: writeLock(root),
download: copyAsset(asset),
}),
/non-symlink path/,