import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import test from 'node:test'; import { BUSINESS_ROUTES, allowedParserModesForRoute, effectiveParserModeForRoute, isParserModeAllowedForRoute, type ParserMode } from '../src/business-routes.js'; import { loadConfig } from '../src/config.js'; import { resolveParserModeSnapshot, TaskError, TaskService } from '../src/task-service.js'; const programOnlyRouteIds = [ 'shared_child_order_batch_create', 'passenger_list_import_independent', 'passenger_list_import_shared_child' ] as const; const parserModes: ParserMode[] = ['ai', 'shadow', 'auto', 'program']; test('the two roster routes and shared-child batch route are hard Program-only in the machine registry', () => { const programOnly = BUSINESS_ROUTES.filter((route) => route.parserPolicy === 'program_only'); assert.deepEqual(programOnly.map((route) => route.routeId), programOnlyRouteIds); for (const route of BUSINESS_ROUTES) { const expectedModes = programOnlyRouteIds.includes(route.routeId as typeof programOnlyRouteIds[number]) ? ['program'] : parserModes; assert.deepEqual(allowedParserModesForRoute(route), expectedModes, route.routeId); for (const mode of parserModes) { assert.equal( isParserModeAllowedForRoute(route, mode), expectedModes.includes(mode), `${route.routeId}:${mode}` ); assert.equal( effectiveParserModeForRoute(route, mode), expectedModes.includes(mode) ? mode : 'program', `${route.routeId}:${mode}:effective` ); } } }); test('hard Program-only task snapshots stay Program with missing or hostile stored settings', async () => { const routeText = (routeId: typeof programOnlyRouteIds[number]) => { const route = BUSINESS_ROUTES.find((candidate) => candidate.routeId === routeId); assert.ok(route); return `${route.directive}\n单号:TEST-ORDER`; }; for (const routeId of programOnlyRouteIds) { for (const storedMode of [null, ...parserModes] as const) { const client = { async query() { return storedMode === null ? { rowCount: 0, rows: [] } : { rowCount: 1, rows: [{ mode: storedMode, revision: 7 }] }; } }; const snapshot = await resolveParserModeSnapshot(client as never, 'test-org', routeText(routeId)); assert.equal(snapshot.routeId, routeId); assert.equal(snapshot.mode, 'program'); assert.equal(snapshot.engineAffinity, null); assert.equal(snapshot.revision, storedMode === null ? 0 : 7); } } const configurableRoute = BUSINESS_ROUTES.find((route) => route.routeId === 'team_order_create'); assert.ok(configurableRoute); const configurable = await resolveParserModeSnapshot({ async query() { return { rowCount: 1, rows: [{ mode: 'shadow', revision: 4 }] }; } } as never, 'test-org', configurableRoute.directive); assert.equal(configurable.mode, 'shadow'); assert.equal(configurable.revision, 4); }); test('the public route mutation rejects AI, Shadow, and Auto before touching settings storage', async () => { const service = new TaskService(loadConfig({ NODE_ENV: 'test', FIELD_ENCRYPTION_KEY: Buffer.alloc(32, 17).toString('base64'), DATABASE_URL: 'postgresql://invalid:invalid@127.0.0.1:1/invalid' })); const context = { organizationId: 'test-org', userId: 'test-user', requestId: 'test-request' }; for (const routeId of programOnlyRouteIds) { for (const mode of parserModes.filter((candidate) => candidate !== 'program')) { await assert.rejects( service.setParserRoutingMode(context, routeId, mode, 0), (error: unknown) => error instanceof TaskError && error.code === 'parser_mode_not_supported' && error.statusCode === 409 && error.details.parser_policy === 'program_only' && Array.isArray(error.details.allowed_modes) && error.details.allowed_modes.join(',') === 'program', `${routeId}:${mode}` ); } } }); test('TaskService exposes and enforces the registry parser policy at every AI override boundary', async () => { const source = await readFile(new URL('../src/task-service.ts', import.meta.url), 'utf8'); assert.match(source, /allowed_modes:/); assert.match(source, /parser_policy:/); assert.match(source, /isParserModeAllowedForRoute\(route, mode\)/); assert.match(source, /parser_mode_not_supported/); assert.match(source, /effectiveParserModeForRoute\(route, 'ai'\)/); assert.match(source, /ai_reparse_not_supported/); assert.match(source, /enforceFixedParserModeForClaim/); });