Files
memind/release-gate/local-stack.test.mjs
T
john d67ebb0c77
Memind CI / Test, build, and release guards (pull_request) Waiting to run
fix(release-gate): isolate PAGE agent runs from split-service MCP routing.
Gate stacks inherited developer MCP env and routed sandbox-fs writes to the
8082 workspace root, so PAGE/DATA scenarios failed with ENOENT despite a
healthy goosed. Sanitize isolated portal env, grant gate skills, and align
CHAT search assertions with the tkmind_search tool name.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 10:43:28 +08:00

84 lines
3.2 KiB
JavaScript

import assert from 'node:assert/strict';
import net from 'node:net';
import test from 'node:test';
import {
assertGatePortAvailable,
buildContainerPgConnectionString,
buildPgConnectionString,
makeIsolatedDatabaseName,
sanitizeIsolatedGatePortalEnv,
} from './local-stack.mjs';
test('isolated database names are bounded and identifier-safe', () => {
const name = makeIsolatedDatabaseName('Gate 2026-07-26 / ABC', 'memind_gate');
assert.equal(name, 'memind_gate_gate_2026_07_26_abc');
assert.match(name, /^[a-z][a-z0-9_]+$/);
assert.ok(name.length <= 63);
});
test('PostgreSQL Unix socket DSN is preserved while database is isolated', () => {
const dsn = buildPgConnectionString(
'postgresql://gate:secret@localhost/base?host=%2Ftmp&port=5433',
'mindspace_gate_abc',
);
const parsed = new URL(dsn);
assert.equal(parsed.pathname, '/mindspace_gate_abc');
assert.equal(parsed.searchParams.get('host'), '/tmp');
assert.equal(parsed.searchParams.get('port'), '5433');
});
test('container PostgreSQL DSN keeps credentials and host while isolating database', () => {
const dsn = buildContainerPgConnectionString(
'postgresql://john:secret@host.docker.internal:5433/mindspace_userdata_dev',
'mindspace_gate_abc',
);
const parsed = new URL(dsn);
assert.equal(parsed.hostname, 'host.docker.internal');
assert.equal(parsed.port, '5433');
assert.equal(parsed.username, 'john');
assert.equal(parsed.password, 'secret');
assert.equal(parsed.pathname, '/mindspace_gate_abc');
});
test('isolated database names reject empty or unsafe prefixes', () => {
assert.throws(() => makeIsolatedDatabaseName('abc', '../bad'), /Unsafe/);
});
test('sanitizeIsolatedGatePortalEnv drops split-service MCP routing', () => {
const sanitized = sanitizeIsolatedGatePortalEnv({
MINDSPACE_SERVER_ADAPTER: 'remote',
MINDSPACE_REMOTE_BASE_URL: 'http://127.0.0.1:8082',
MINDSPACE_REMOTE_AUTH_TOKEN: 'local-dev-secret',
MINDSPACE_MCP_BASE_URL: 'http://127.0.0.1:8082',
MINDSPACE_MCP_TOKEN_SECRET: 'local-dev-secret',
MINDSPACE_AGENT_API_BASE_URL: 'http://127.0.0.1:8081/api',
}, { port: 19087, runtimeProfile: 'local' });
assert.equal(sanitized.MINDSPACE_SERVER_ADAPTER, 'local');
assert.equal(sanitized.MEMIND_RUNTIME_PROFILE, 'local');
assert.equal(sanitized.H5_PORTAL_BASE_URL, 'http://127.0.0.1:19087');
assert.equal(sanitized.MINDSPACE_AGENT_API_BASE_URL, 'http://127.0.0.1:19087/api');
assert.equal(sanitized.MINDSPACE_REMOTE_BASE_URL, undefined);
assert.equal(sanitized.MINDSPACE_MCP_BASE_URL, undefined);
assert.equal(sanitized.MINDSPACE_MCP_TOKEN_SECRET, undefined);
});
test('assertGatePortAvailable rejects occupied loopback ports', async () => {
const server = net.createServer();
await new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
const address = server.address();
assert.ok(address && typeof address === 'object');
await assert.rejects(
() => assertGatePortAvailable(address.port),
/already in use/,
);
await new Promise((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
await assertGatePortAvailable(address.port);
});