import assert from 'node:assert/strict'; import test from 'node:test'; import { agentCodeRunAdminConfigInternals, createAgentCodeRunAdminConfigService, isTaskTypeAllowedByCodeRunPolicy, isUserAllowedByCodeRunPolicy, } from './agent-code-run-admin-config.mjs'; function createMemoryPool(initialRow = null) { const state = { row: initialRow }; return { state, async query(sql, params = []) { const normalized = String(sql).replace(/\s+/g, ' ').trim(); if (normalized.startsWith('CREATE TABLE')) return [[]]; if (normalized.includes('SELECT config_json')) { return [state.row ? [state.row] : []]; } if (normalized.includes('INSERT INTO h5_agent_code_run_config')) { state.row = { config_json: params[1], updated_by: params[2], updated_at: params[3], }; return [{ affectedRows: 1 }]; } return [[]]; }, }; } test('default policy is fail closed', async () => { const service = createAgentCodeRunAdminConfigService(createMemoryPool(), { env: {} }); const policy = await service.getEffectivePolicy('user-1'); assert.equal(policy.enabled, false); assert.equal(policy.clientEnabled, false); assert.equal(policy.pageDataDevAutodetect, false); assert.equal(policy.source, 'default'); }); test('env migration activates when legacy env flags are set', async () => { const service = createAgentCodeRunAdminConfigService(createMemoryPool(), { env: { MEMIND_AGENT_CODE_RUNS_ENABLED: '1', VITE_AGENT_PAGE_DATA_DEV_AUTODETECT: '1', MEMIND_AGENT_CODE_RUNS_USER_IDS: 'user-a', }, }); const policy = await service.getEffectivePolicy('user-a'); assert.equal(policy.source, 'env-migration'); assert.equal(policy.enabled, true); assert.equal(policy.pageDataDevAutodetect, true); assert.equal(policy.userAllowed, true); assert.equal(isUserAllowedByCodeRunPolicy('user-b', policy), false); }); test('admin-db config overrides env migration defaults', async () => { const pool = createMemoryPool({ config_json: JSON.stringify({ codeRun: { enabled: true, clientEnabled: true, pageDataDevAutodetect: false, generalAutodetect: false, requireValidation: true, userAllowlist: [], taskTypeAllowlist: ['page_data_dev'], }, pageDataDev: { autodetect: true }, }), updated_by: 'admin-1', updated_at: 123, }); const service = createAgentCodeRunAdminConfigService(pool, { env: { MEMIND_AGENT_CODE_RUNS_ENABLED: '0' }, }); const policy = await service.getEffectivePolicy('user-1'); assert.equal(policy.source, 'admin-db'); assert.equal(policy.enabled, true); assert.equal(policy.pageDataDevAutodetect, true); assert.equal(isTaskTypeAllowedByCodeRunPolicy('page_data_dev', policy), true); assert.equal(isTaskTypeAllowedByCodeRunPolicy('h5_chat_code_task', policy), false); }); test('updateAdminConfig persists patch to database', async () => { const pool = createMemoryPool(); const service = createAgentCodeRunAdminConfigService(pool, { env: {} }); const saved = await service.updateAdminConfig( { config: { codeRun: { enabled: true, clientEnabled: true }, pageDataDev: { autodetect: true }, }, }, { updatedBy: 'admin-1' }, ); assert.equal(saved.source, 'admin-db'); assert.equal(saved.config.codeRun.enabled, true); assert.equal(saved.config.pageDataDev.autodetect, true); const clientPolicy = await service.getPublicClientPolicy('user-1'); assert.equal(clientPolicy.codeRun.enabled, true); assert.equal(clientPolicy.codeRun.pageDataDevAutodetect, true); }); test('MEMIND_CODE_RUN_POLICY_SOURCE=env locks admin updates', async () => { const service = createAgentCodeRunAdminConfigService(createMemoryPool(), { env: { MEMIND_CODE_RUN_POLICY_SOURCE: 'env', MEMIND_AGENT_CODE_RUNS_ENABLED: '1' }, }); await assert.rejects( () => service.updateAdminConfig({ config: { codeRun: { enabled: false } } }), /不允许通过后台修改/, ); }); test('getPublicClientPolicy disables client flags when user not allowlisted', async () => { const config = agentCodeRunAdminConfigInternals.defaultConfigShape(); config.codeRun.enabled = true; config.codeRun.clientEnabled = true; config.codeRun.userAllowlist = ['allowed-user']; config.pageDataDev.autodetect = true; const pool = createMemoryPool({ config_json: JSON.stringify(config), updated_by: null, updated_at: 1, }); const service = createAgentCodeRunAdminConfigService(pool, { env: {} }); const denied = await service.getPublicClientPolicy('other-user'); assert.equal(denied.codeRun.enabled, false); const allowed = await service.getPublicClientPolicy('allowed-user'); assert.equal(allowed.codeRun.enabled, true); assert.equal(allowed.codeRun.pageDataDevAutodetect, true); }); test('listRecentPageDataDevRuns filters page data dev task types', async () => { const pool = { async query(sql) { const normalized = String(sql).replace(/\s+/g, ' ').trim(); if (normalized.includes('FROM h5_agent_runs')) { return [[ { id: 'run-1', user_id: 'user-1', request_id: 'req-1', status: 'failed', error_message: 'boom', created_at: 1, updated_at: 2, user_message_json: JSON.stringify({ metadata: { memindRun: { taskType: 'page_data_dev', executor: 'aider' } }, }), }, { id: 'run-2', user_id: 'user-1', request_id: 'req-2', status: 'succeeded', error_message: null, created_at: 3, updated_at: 4, user_message_json: JSON.stringify({ metadata: { memindRun: { taskType: 'h5_chat_code_task' } }, }), }, ]]; } return [[]]; }, }; const service = createAgentCodeRunAdminConfigService(pool, { env: {} }); const result = await service.listRecentPageDataDevRuns({ limit: 10 }); assert.equal(result.runs.length, 1); assert.equal(result.runs[0].taskType, 'page_data_dev'); assert.equal(result.runs[0].executor, 'aider'); });