Files
memind/services/orchestrator/admin-config.test.mjs
T
2026-07-24 22:44:26 +08:00

211 lines
7.2 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
createOrchestratorAdminConfigService,
defaultOrchestratorConfig,
normalizeOrchestratorConfig,
} from './admin-config.mjs';
function createPool() {
let row = null;
return {
async query(sql, params = []) {
if (sql.includes('CREATE TABLE')) return [[], []];
if (sql.includes('SELECT config_json')) return [[...(row ? [row] : [])], []];
if (sql.includes('INSERT INTO')) {
row = {
config_json: params[1],
config_version: params[2],
updated_by: params[3],
updated_at: params[4],
};
return [{ affectedRows: 1 }, []];
}
throw new Error(`Unexpected SQL: ${sql}`);
},
};
}
test('orchestrator config defaults to a disabled native-safe runtime', async () => {
const service = createOrchestratorAdminConfigService(createPool(), { env: {} });
const state = await service.getAdminConfig();
assert.equal(state.config.mode, 'off');
assert.equal(state.config.primaryEngine, 'langgraph');
assert.equal(state.runtime.effective, false);
assert.equal(state.runtime.reason, 'mode_off');
assert.equal(state.engines.find((engine) => engine.id === 'native').configured, true);
assert.equal(state.engines.find((engine) => engine.id === 'langgraph').configured, false);
});
test('orchestrator config normalizes unsafe values and keeps a workflow allowlist', () => {
const normalized = normalizeOrchestratorConfig({
mode: 'active',
serviceUrl: 'file:///tmp/graph',
requestTimeoutMs: 1,
rolloutPercent: 500,
workflowAllowlist: ['code-run-v1', 'INVALID WORKFLOW', 'code-run-v1'],
});
assert.equal(normalized.serviceUrl, '');
assert.equal(normalized.requestTimeoutMs, 500);
assert.equal(normalized.rolloutPercent, 100);
assert.deepEqual(normalized.workflowAllowlist, ['code-run-v1']);
});
test('orchestrator config persists versioned admin updates and selects canary users', async () => {
const service = createOrchestratorAdminConfigService(createPool(), { env: {} });
const updated = await service.updateAdminConfig({
...defaultOrchestratorConfig(),
mode: 'canary',
serviceUrl: 'http://127.0.0.1:8093',
rolloutPercent: 0,
userAllowlist: ['user-1'],
}, { updatedBy: 'admin-1' });
assert.equal(updated.configVersion, 1);
assert.equal(updated.updatedBy, 'admin-1');
assert.equal(updated.runtime.effective, true);
const selected = await service.selectEngine({
runId: 'run-1',
userId: 'user-1',
workflowName: 'code-run-v1',
});
assert.equal(selected.engine, 'native');
assert.equal(selected.candidateEngine, 'langgraph');
assert.equal(selected.reason, 'execution_gate_disabled');
assert.equal(selected.candidateReason, 'user_allowlist');
assert.equal(selected.dryRun, true);
const native = await service.selectEngine({
runId: 'run-2',
userId: 'user-2',
workflowName: 'code-run-v1',
});
assert.equal(native.engine, 'native');
assert.equal(native.candidateEngine, 'native');
assert.equal(native.reason, 'canary_not_selected');
});
test('orchestrator execution handoff remains hard-disabled when Active is requested', async () => {
const service = createOrchestratorAdminConfigService(createPool(), { env: {} });
await service.updateAdminConfig({
mode: 'active',
serviceUrl: 'http://127.0.0.1:8093',
});
const runtime = await service.getRuntimeState();
assert.equal(runtime.runtime.plansLangGraph, true);
assert.equal(runtime.runtime.executesLangGraph, false);
assert.deepEqual(runtime.runtime.executionHandoff, {
implemented: false,
requested: true,
enabled: false,
reason: 'phase3_dry_run_only',
});
const selected = await service.selectEngine({
runId: 'run-1',
userId: 'user-1',
workflowName: 'code-run-v1',
});
assert.equal(selected.engine, 'native');
assert.equal(selected.candidateEngine, 'langgraph');
assert.equal(selected.dryRun, true);
});
test('orchestrator keeps a Native primary as a non-dry-run Native selection', async () => {
const service = createOrchestratorAdminConfigService(createPool(), { env: {} });
await service.updateAdminConfig({
mode: 'active',
primaryEngine: 'native',
});
const selected = await service.selectEngine({
runId: 'run-native',
workflowName: 'code-run-v1',
});
assert.equal(selected.engine, 'native');
assert.equal(selected.candidateEngine, 'native');
assert.equal(selected.reason, 'active');
assert.equal(selected.dryRun, false);
});
test('Shadow mode evaluates the Canary rollout while Native remains effective', async () => {
const service = createOrchestratorAdminConfigService(createPool(), { env: {} });
await service.updateAdminConfig({
mode: 'shadow',
serviceUrl: 'http://127.0.0.1:8093',
rolloutPercent: 0,
userAllowlist: ['user-preview'],
});
const selected = await service.selectEngine({
runId: 'run-preview-selected',
userId: 'user-preview',
workflowName: 'code-run-v1',
});
assert.equal(selected.engine, 'native');
assert.equal(selected.shadowEngine, 'langgraph');
assert.equal(selected.candidateEngine, 'langgraph');
assert.equal(selected.candidateReason, 'user_allowlist');
assert.equal(selected.dryRun, true);
const native = await service.selectEngine({
runId: 'run-preview-native',
userId: 'user-native',
workflowName: 'code-run-v1',
});
assert.equal(native.engine, 'native');
assert.equal(native.shadowEngine, 'langgraph');
assert.equal(native.candidateEngine, 'native');
assert.equal(native.candidateReason, 'canary_not_selected');
assert.equal(native.dryRun, true);
});
test('orchestrator emergency kill switch always forces native selection', async () => {
const service = createOrchestratorAdminConfigService(createPool(), {
env: { MEMIND_ORCHESTRATOR_KILL_SWITCH: '1' },
});
await service.updateAdminConfig({
mode: 'active',
serviceUrl: 'http://127.0.0.1:8093',
});
const selected = await service.selectEngine({
runId: 'run-1',
userId: 'user-1',
workflowName: 'code-run-v1',
});
assert.equal(selected.engine, 'native');
assert.equal(selected.reason, 'kill_switch');
});
test('orchestrator runtime probe reports sanitized service health', async () => {
let requestedUrl = null;
const service = createOrchestratorAdminConfigService(createPool(), {
env: {},
fetchImpl: async (url) => {
requestedUrl = url;
return new Response(JSON.stringify({
status: 'ok',
service: 'memind-langgraph-orchestrator',
checkpoint: { kind: 'postgres', durable: true, password: 'must-not-pass-through' },
execution: 'observe-only',
ignoredSecret: 'must-not-pass-through',
}), {
status: 200,
headers: { 'content-type': 'application/json' },
});
},
});
await service.updateAdminConfig({
mode: 'shadow',
serviceUrl: 'http://127.0.0.1:8093',
});
const runtime = await service.getRuntimeState({ probe: true });
assert.equal(requestedUrl, 'http://127.0.0.1:8093/ready');
assert.equal(runtime.serviceHealth.ok, true);
assert.equal(runtime.serviceHealth.details.checkpoint.durable, true);
assert.equal('password' in runtime.serviceHealth.details.checkpoint, false);
assert.equal('ignoredSecret' in runtime.serviceHealth.details, false);
});