import test from 'node:test'; import assert from 'node:assert/strict'; import express from 'express'; import { once } from 'node:events'; import { createAdminApi } from './admin-routes.mjs'; async function startTestServer(router) { const app = express(); app.use('/admin-api', router); const server = app.listen(0, '127.0.0.1'); await once(server, 'listening'); const address = server.address(); return { server, baseUrl: `http://127.0.0.1:${address.port}`, close: async () => { server.close(); await once(server, 'close'); }, }; } test('admin memory-v2 config routes expose config and runtime state', async () => { const updates = []; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe(token) { if (token !== 'token-admin') return null; return { id: 'admin-1', role: 'admin' }; }, }, llmProviderService: null, memoryV2ConfigService: { async getAdminConfig() { return { config: { chatIntentRouter: { enabled: true } }, updatedAt: 123 }; }, async updateAdminConfig(patch, { updatedBy }) { updates.push({ patch, updatedBy }); return { config: patch, updatedAt: 456, updatedBy }; }, async getRuntimeState() { return { source: 'admin-db', overrides: { MEMIND_CHAT_LLM_ROUTER_ENABLED: '1' } }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const configRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/config`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(configRes.status, 200); assert.deepEqual(await configRes.json(), { config: { chatIntentRouter: { enabled: true } }, updatedAt: 123, }); const updateRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/config`, { method: 'PATCH', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin', }, body: JSON.stringify({ chatIntentRouter: { enabled: false } }), }); assert.equal(updateRes.status, 200); assert.deepEqual(updates, [{ patch: { chatIntentRouter: { enabled: false } }, updatedBy: 'admin-1', }]); const runtimeRes = await fetch(`${server.baseUrl}/admin-api/memory-v2/runtime`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(runtimeRes.status, 200); assert.deepEqual(await runtimeRes.json(), { source: 'admin-db', overrides: { MEMIND_CHAT_LLM_ROUTER_ENABLED: '1' }, }); } finally { await server.close(); } }); test('admin orchestrator routes expose a versioned plug-in control plane', async () => { const updates = []; const state = { config: { mode: 'off', primaryEngine: 'langgraph', fallbackEngine: 'native', serviceUrl: '', requestTimeoutMs: 5000, rolloutPercent: 0, userAllowlist: [], workflowAllowlist: ['code-run-v1'], fallbackToNative: true, requireHealthy: true, }, configVersion: 1, runtime: { effective: false, reason: 'mode_off' }, engines: [{ id: 'native', configured: true }, { id: 'langgraph', configured: false }], }; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; }, }, llmProviderService: null, memoryV2ConfigService: null, orchestratorConfigService: { async getAdminConfig() { return state; }, async updateAdminConfig(config, context) { updates.push({ config, context }); return { ...state, config: { ...state.config, ...config }, configVersion: 2 }; }, async getRuntimeState(options) { assert.deepEqual(options, { probe: true }); return { ...state, source: 'admin-db', serviceHealth: { ok: true, status: 'healthy' }, }; }, }, orchestratorObservabilityService: { async listExecutionPlans(options) { assert.deepEqual(options, { hours: '24', limit: '50', selection: 'candidate', }); return { metrics: { decisions: 3, candidateSelections: 2 }, plans: [{ runId: 'run-plan-1', candidateEngine: 'langgraph' }], }; }, async getCanaryReadiness() { return { ready: false, recommendation: 'keep_shadow', blockers: ['sample_volume'], samples: { eligibleObservations: 1 }, }; }, async listShadowRuns(options) { assert.deepEqual(options, { hours: '12', limit: '25', status: 'failed' }); return { metrics: { observations: 1, successes: 0, failures: 1 }, runs: [{ runId: 'run-shadow-1', shadowStatus: 'failed' }], }; }, async getShadowRun(runId) { assert.equal(runId, 'run-shadow-1'); return { native: { runId, status: 'succeeded' }, remote: { available: true, events: [{ type: 'workflow_validated' }] }, }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const configResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/config`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(configResponse.status, 200); assert.equal((await configResponse.json()).config.mode, 'off'); const updateResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/config`, { method: 'PATCH', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin', }, body: JSON.stringify({ config: { mode: 'shadow', serviceUrl: 'http://127.0.0.1:8093' } }), }); assert.equal(updateResponse.status, 200); assert.equal((await updateResponse.json()).configVersion, 2); assert.deepEqual(updates, [{ config: { mode: 'shadow', serviceUrl: 'http://127.0.0.1:8093' }, context: { updatedBy: 'admin-1' }, }]); const runtimeResponse = await fetch(`${server.baseUrl}/admin-api/orchestrator/runtime`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(runtimeResponse.status, 200); const runtimeBody = await runtimeResponse.json(); assert.equal(runtimeBody.source, 'admin-db'); assert.equal(runtimeBody.serviceHealth.status, 'healthy'); const shadowRunsResponse = await fetch( `${server.baseUrl}/admin-api/orchestrator/shadow-runs?hours=12&limit=25&status=failed`, { headers: { cookie: 'h5_user_session=token-admin' } }, ); assert.equal(shadowRunsResponse.status, 200); assert.equal((await shadowRunsResponse.json()).metrics.failures, 1); const executionPlansResponse = await fetch( `${server.baseUrl}/admin-api/orchestrator/execution-plans?hours=24&limit=50&selection=candidate`, { headers: { cookie: 'h5_user_session=token-admin' } }, ); assert.equal(executionPlansResponse.status, 200); const executionPlansBody = await executionPlansResponse.json(); assert.equal(executionPlansBody.metrics.decisions, 3); assert.equal(executionPlansBody.plans[0].candidateEngine, 'langgraph'); const readinessResponse = await fetch( `${server.baseUrl}/admin-api/orchestrator/canary-readiness`, { headers: { cookie: 'h5_user_session=token-admin' } }, ); assert.equal(readinessResponse.status, 200); const readinessBody = await readinessResponse.json(); assert.equal(readinessBody.ready, false); assert.deepEqual(readinessBody.blockers, ['sample_volume']); const shadowRunResponse = await fetch( `${server.baseUrl}/admin-api/orchestrator/shadow-runs/run-shadow-1`, { headers: { cookie: 'h5_user_session=token-admin' } }, ); assert.equal(shadowRunResponse.status, 200); assert.equal((await shadowRunResponse.json()).remote.available, true); } finally { await server.close(); } }); test('admin system disclosure policy routes version config through the injected control-plane service', async () => { const updates = []; const config = { enabled: true, mode: 'shadow', refusalText: '不提供内部技术信息。', productNames: ['tkmind'], selfReferences: ['本系统'], categories: { architecture: true }, }; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; }, }, llmProviderService: null, memoryV2ConfigService: null, systemDisclosurePolicyService: { async getAdminConfig() { return { config, policyVersion: 2, source: 'admin-db' }; }, async updateAdminConfig(patch, context) { updates.push({ patch, context }); return { config: patch, policyVersion: 3, source: 'admin-db' }; }, getRuntimeState() { return { config, policyVersion: 2, source: 'admin-db', refreshedAt: 123 }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const getResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/config`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(getResponse.status, 200); assert.equal((await getResponse.json()).policyVersion, 2); const updateResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/config`, { method: 'PUT', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin', }, body: JSON.stringify({ config: { ...config, mode: 'enforce' } }), }); assert.equal(updateResponse.status, 200); assert.equal((await updateResponse.json()).policyVersion, 3); assert.deepEqual(updates, [{ patch: { ...config, mode: 'enforce' }, context: { updatedBy: 'admin-1' }, }]); const runtimeResponse = await fetch(`${server.baseUrl}/admin-api/system-disclosure-policy/runtime`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(runtimeResponse.status, 200); assert.equal((await runtimeResponse.json()).refreshedAt, 123); } finally { await server.close(); } }); test('admin MindSearch routes persist only through injected control-plane service', async () => { const updates = []; const testedServices = []; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; } }, llmProviderService: null, memoryV2ConfigService: null, mindSearchConfigService: { async getAdminConfig() { return { config: { enabled: false, mode: 'off', providers: { searxng: false, github: false, reader: false } }, source: 'env' }; }, async updateAdminConfig(patch, context) { updates.push({ patch, context }); return { config: { enabled: true, mode: 'shadow', providers: { searxng: true, github: false, reader: false } }, source: 'admin' }; }, async getRuntimeState() { return { effective: false, mode: 'off' }; }, async testService(serviceId) { testedServices.push(serviceId); return { ok: true, serviceId, latencyMs: 3 }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const config = await fetch(`${server.baseUrl}/admin-api/mindsearch/config`, { headers: { cookie: 'h5_user_session=token-admin' } }); assert.equal(config.status, 200); const update = await fetch(`${server.baseUrl}/admin-api/mindsearch/config`, { method: 'PATCH', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin' }, body: JSON.stringify({ enabled: true, mode: 'shadow' }) }); assert.equal(update.status, 200); assert.deepEqual(updates, [{ patch: { enabled: true, mode: 'shadow' }, context: { updatedBy: 'admin-1' } }]); const runtime = await fetch(`${server.baseUrl}/admin-api/mindsearch/runtime`, { headers: { cookie: 'h5_user_session=token-admin' } }); assert.deepEqual(await runtime.json(), { effective: false, mode: 'off' }); const serviceTest = await fetch(`${server.baseUrl}/admin-api/mindsearch/services/searxng/test`, { method: 'POST', headers: { cookie: 'h5_user_session=token-admin' } }); assert.deepEqual(await serviceTest.json(), { ok: true, serviceId: 'searxng', latencyMs: 3 }); assert.deepEqual(testedServices, ['searxng']); } finally { await server.close(); } }); test('admin asset gateway routes preserve an explicit, admin-only control plane', async () => { const calls = []; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe() { return { id: 'admin-1', role: 'admin' }; } }, llmProviderService: null, memoryV2ConfigService: null, assetGatewayConfigService: { async getConfig() { return { enabled: false, plugins: [] }; }, async updateGlobalConfig(payload, context) { calls.push({ type: 'global', payload, context }); return { enabled: true }; }, async updatePluginConfig(pluginId, payload, context) { calls.push({ type: 'plugin', pluginId, payload, context }); return { ok: true, config: { enabled: true, plugins: [] } }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const read = await fetch(`${server.baseUrl}/admin-api/asset-gateway/config`, { headers: { cookie: 'h5_user_session=token-admin' }, }); assert.equal(read.status, 200); assert.deepEqual(await read.json(), { enabled: false, plugins: [] }); const update = await fetch(`${server.baseUrl}/admin-api/asset-gateway/plugins/asset-generate`, { method: 'PUT', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin' }, body: JSON.stringify({ enabled: true, provider: 'flux-schnell' }), }); assert.equal(update.status, 200); assert.equal(calls[0].pluginId, 'asset-generate'); assert.equal(calls[0].context.updatedBy, 'admin-1'); } finally { await server.close(); } }); test('admin system test route executes shared validation service', async () => { const calls = []; const router = createAdminApi({ jsonBody: express.json(), getToken() { return 'token-admin'; }, userAuth: { async getMe(token) { if (token !== 'token-admin') return null; return { id: 'admin-1', role: 'admin' }; }, }, llmProviderService: null, memoryV2ConfigService: null, adminSystemTestService: { async runSkillValidation(input) { calls.push(input); return { ok: true, selectedSkill: input.skillName, account: { username: input.username }, summary: { passed: 1, warnings: 0, failed: 0 }, steps: [], issues: [], }; }, }, plazaPosts: null, plazaOps: null, wechatAdmin: null, subscriptionService: null, }); const server = await startTestServer(router); try { const response = await fetch(`${server.baseUrl}/admin-api/system-tests/skill-validation`, { method: 'POST', headers: { 'content-type': 'application/json', cookie: 'h5_user_session=token-admin', }, body: JSON.stringify({ username: 'john', password: 'secret', skillName: 'service-integration-smoke', }), }); assert.equal(response.status, 200); assert.deepEqual(calls, [{ username: 'john', password: 'secret', skillName: 'service-integration-smoke', }]); assert.equal((await response.json()).ok, true); } finally { await server.close(); } });