mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-06 17:49:47 +00:00
Externalizing the integration templates (#1492/#1493) and the UI bundle
(#1501/#1503) was done to reduce the Microsoft `Wacatac.B!ml` surface. It did
not work: across dry runs the flagged artifact count stayed at ~3 and the
detections merely moved between artifacts.
Dissection of run 31286803592 shows there is no structural cause to fix. The
verdicts split across every axis at once — linux-amd64 (dynamic) flagged while
linux-amd64-portable (static) is clean, but linux-arm64 (dynamic) clean while
linux-arm64-portable (static) is flagged. The two macOS binaries have identical
segment structure and split clean/flagged. Siblings from one build landed in
different variant buckets (.B vs .C). Entropy is low everywhere
(code_vectors.bin 4.166, grammar tables 3.464 bits/byte, against 7.5-8.0 for
packed payloads), so the packed-payload hypothesis is excluded too.
So the complexity bought nothing, and installation goes back to being
self-contained: one binary that carries its own UI and agent integration
templates, with no adjacent data file that has to resolve before `install`
works. Only the UI-capable composition ships from now on, under the historical
unsuffixed archive name.
Removed: src/ui/asset_pack.{c,h}, asset_pack_stub.c, asset_manifest_stub.c,
scripts/pack-ui-assets.mjs, src/cli/integration_assets.{c,h},
assets/cbm-integrations.json, scripts/gen-integrations-hash.sh, the
--verify-runtime-assets probe (nothing adjacent left to verify), and the
composition gates A6/A7 whose property is now deliberately inverted.
Restored: scripts/embed-frontend.sh, src/ui/embedded_{assets.h,stub.c}, the
compiled-in hook/adapter template bodies, and the embed/EMBED_OBJS build path.
Kept from the reverted commits, re-applied by hand where a wholesale file
restore would have dropped them:
- cbm_module_path_utf8() in both self-path sites. GetModuleFileNameA renders
through the ANSI code page and mangles non-ASCII install paths.
- the /__cbm/ui-readiness HMAC proof, secure_random and cbm_hmac_sha256, so
`daemon start --open` still waits for a genuine CBM listener.
- X-Content-Type-Options: nosniff on served assets.
- the MinGW noexecstack gate, -lbcrypt, and the cppcheck/zip CI fixes.
Archives are now codebase-memory-mcp-<os>-<arch>[-portable] with exactly four
members (binary, LICENSE, installer, THIRD_PARTY_NOTICES.md). That restores the
names every static package manifest already points at — aur, chocolatey,
homebrew, scoop, winget and glama were all broken by the -ui- rename.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
119 lines
3.7 KiB
JavaScript
119 lines
3.7 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
const vm = require('node:vm');
|
|
|
|
class ExitSignal extends Error {
|
|
constructor(code) {
|
|
super(`process.exit(${code})`);
|
|
this.code = code;
|
|
}
|
|
}
|
|
|
|
function runShim(targetPlatform, arguments_, childStatus) {
|
|
const shimPath = path.join(__dirname, '..', 'bin.js');
|
|
const source = fs.readFileSync(shimPath, 'utf8').replace(/^#![^\n]*\n/, '');
|
|
const calls = [];
|
|
let stderr = '';
|
|
|
|
const fakeProcess = {
|
|
platform: targetPlatform,
|
|
argv: ['node.exe', shimPath, ...arguments_],
|
|
execPath: 'node.exe',
|
|
stderr: { write: (text) => { stderr += String(text); } },
|
|
exit: (code) => { throw new ExitSignal(code); },
|
|
};
|
|
const fakeFs = {
|
|
existsSync: () => true,
|
|
};
|
|
const fakeChildProcess = {
|
|
spawnSync: (executable, args, options) => {
|
|
calls.push({ executable, args, options });
|
|
return { status: calls.length === 1 ? 0 : childStatus };
|
|
},
|
|
};
|
|
const sandbox = {
|
|
__dirname: path.dirname(shimPath),
|
|
__filename: shimPath,
|
|
Buffer,
|
|
clearTimeout,
|
|
console,
|
|
exports: {},
|
|
module: { exports: {} },
|
|
process: fakeProcess,
|
|
require: (specifier) => {
|
|
if (specifier === 'fs') return fakeFs;
|
|
if (specifier === 'child_process') return fakeChildProcess;
|
|
return require(specifier);
|
|
},
|
|
setTimeout,
|
|
};
|
|
|
|
let exitCode = null;
|
|
try {
|
|
vm.runInNewContext(source, sandbox, { filename: shimPath });
|
|
} catch (error) {
|
|
if (!(error instanceof ExitSignal)) throw error;
|
|
exitCode = error.code;
|
|
}
|
|
return { calls, exitCode, stderr };
|
|
}
|
|
|
|
test('Windows npm shim probes and executes the cached launcher', () => {
|
|
const observed = runShim('win32', ['--version'], 0);
|
|
|
|
assert.equal(observed.exitCode, 0);
|
|
assert.equal(observed.calls.length, 2);
|
|
for (const call of observed.calls) {
|
|
assert.equal(path.basename(call.executable), 'codebase-memory-mcp.exe');
|
|
assert.notEqual(
|
|
path.basename(call.executable),
|
|
'codebase-memory-mcp.payload.exe',
|
|
);
|
|
}
|
|
assert.deepEqual(Array.from(observed.calls[1].args), ['--version']);
|
|
assert.equal(observed.calls[1].options.stdio, 'inherit');
|
|
});
|
|
|
|
test('Windows npm shim keeps package-manager guidance after launcher refusal', () => {
|
|
const observed = runShim('win32', ['update'], 1);
|
|
|
|
assert.equal(observed.exitCode, 1);
|
|
assert.equal(path.basename(observed.calls[1].executable), 'codebase-memory-mcp.exe');
|
|
assert.match(observed.stderr, /npm install codebase-memory-mcp@latest/);
|
|
assert.match(observed.stderr, /install --yes/);
|
|
});
|
|
|
|
test('non-Windows npm shim keeps its native payload execution path', () => {
|
|
const observed = runShim('darwin', ['--version'], 0);
|
|
|
|
assert.equal(observed.exitCode, 0);
|
|
assert.equal(observed.calls.length, 1);
|
|
assert.equal(path.basename(observed.calls[0].executable), 'codebase-memory-mcp');
|
|
});
|
|
|
|
test('PowerShell install mutation runs through the downloaded binary', () => {
|
|
const installer = fs.readFileSync(
|
|
path.join(__dirname, '..', '..', '..', 'install.ps1'),
|
|
'utf8',
|
|
);
|
|
|
|
assert.match(
|
|
installer,
|
|
/^\s*\$candidateVersion\s*=\s*&\s*\$DownloadedBinary\s+--version\b/m,
|
|
);
|
|
assert.match(
|
|
installer,
|
|
/^\s*&\s*\$DownloadedBinary\s+@InstallArgs\b/m,
|
|
);
|
|
// One binary ships per platform — no launcher/payload pair to resolve.
|
|
assert.doesNotMatch(installer, /payload/i);
|
|
// A running .exe cannot be overwritten, so an in-place update has to retire
|
|
// the existing binary by renaming it aside first. This script IS the Windows
|
|
// update path, so losing that step would silently break every update.
|
|
assert.match(installer, /Move-Item[\s\S]{0,80}\$Dest[\s\S]{0,40}\$retired/);
|
|
});
|