import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import test from 'node:test'; async function source(path: string): Promise { return readFile(new URL(path, import.meta.url), 'utf8'); } test('account migration adds roles, actor attribution, and reversible archive without purging history', async () => { const sql = await source('../migrations/015_account_roles_and_task_audit.sql'); assert.match(sql, /CHECK \(role IN \('admin', 'user'\)\)/); assert.match(sql, /must_change_password boolean NOT NULL DEFAULT false/); assert.match(sql, /password_changed_at timestamptz NOT NULL DEFAULT now\(\)/); assert.match(sql, /idempotency_keys[\s\S]+actor_user_id uuid REFERENCES users\(id\)/); assert.match(sql, /idempotency_keys_actor_unique_idx/); assert.match(sql, /idempotency_keys_system_unique_idx/); assert.match(sql, /actor_user_id uuid REFERENCES users\(id\)/); assert.match(sql, /input_source IN \('manual', 'agentbus', 'reparse', 'system'\)/); assert.match(sql, /task_input_attachments[\s\S]+created_by uuid REFERENCES users\(id\)/); assert.match(sql, /archived_at timestamptz/); assert.match(sql, /archived_by uuid REFERENCES users\(id\)/); assert.doesNotMatch(sql, /DELETE\s+FROM/i); }); test('team-lead migration adds the role and bounded dashboard indexes without a tenant concept', async () => { const sql = await source('../migrations/016_team_lead_operations_dashboard.sql'); assert.match(sql, /CHECK \(role IN \('admin', 'team_lead', 'user'\)\)/); assert.match(sql, /tasks_operations_dashboard_created_idx/); assert.match(sql, /tasks_operations_dashboard_actor_idx/); assert.match(sql, /tasks_operations_dashboard_status_idx/); assert.match(sql, /tasks_operations_dashboard_business_idx/); assert.match(sql, /WHERE source = 'manual'/); assert.doesNotMatch(sql, /CREATE TABLE\s+(?:organizations|tenants)/i); assert.doesNotMatch(sql, /DELETE\s+FROM/i); }); test('business authorization migration adds a fail-closed per-user allowlist for all registered routes', async () => { const sql = await source('../migrations/017_user_business_route_authorizations.sql'); assert.match(sql, /business_authorization_revision integer NOT NULL DEFAULT 0/); assert.match(sql, /CREATE TABLE IF NOT EXISTS user_business_route_authorizations/); assert.match(sql, /PRIMARY KEY \(organization_id, user_id, route_id\)/); assert.match(sql, /granted_by uuid REFERENCES users\(id\)/); assert.match(sql, /FOREIGN KEY \(organization_id, user_id\)[\s\S]+REFERENCES users \(organization_id, id\)/); assert.match(sql, /FOREIGN KEY \(organization_id, granted_by\)[\s\S]+REFERENCES users \(organization_id, id\)/); for (const routeId of [ 'team_order_create', 'passenger_list_import_independent', 'arrangement_hotel_create', 'order_update_independent', 'order_cancel', 'confirmation_export' ]) { assert.match(sql, new RegExp(`'${routeId}'`)); } assert.doesNotMatch(sql, /INSERT INTO user_business_route_authorizations[\s\S]+SELECT[\s\S]+FROM users/i); }); test('AgentBus account-worker migration adds fail-closed channel, task, browser, and ERP identity ownership', async () => { const sql = await source('../migrations/018_agentbus_account_workers.sql'); assert.match(sql, /ADD COLUMN IF NOT EXISTS erp_account text/); assert.match(sql, /users_org_erp_account_unique_idx/); assert.match(sql, /ADD COLUMN IF NOT EXISTS owner_user_id uuid/); assert.match(sql, /FOREIGN KEY \(organization_id, owner_user_id\)[\s\S]+REFERENCES users \(organization_id, id\)/); assert.match(sql, /user_channels_owner_unique_idx/); assert.match(sql, /ADD COLUMN IF NOT EXISTS assigned_user_id uuid/); assert.match(sql, /FOREIGN KEY \(organization_id, assigned_user_id\)[\s\S]+REFERENCES users \(organization_id, id\)/); assert.match(sql, /source = 'manual'[\s\S]+created_by IS NOT NULL/); assert.match(sql, /erp_account_verified boolean NOT NULL DEFAULT false/); assert.match(sql, /browser_connections_active_user_unique_idx/); assert.match(sql, /status = 'superseded'/); assert.match(sql, /owner_user_id IS NULL[\s\S]+enabled = true/); }); test('administrator task-isolation migration removes legacy bindings and rejects future data-plane principals', async () => { const sql = await source('../migrations/021_admin_task_data_plane_isolation.sql'); assert.match(sql, /UPDATE tasks task[\s\S]+assigned_user_id = NULL[\s\S]+account\.role = 'admin'/); assert.match(sql, /UPDATE user_channels channel[\s\S]+owner_user_id = NULL[\s\S]+account\.role = 'admin'/); assert.match(sql, /UPDATE browser_connections connection[\s\S]+status = 'superseded'[\s\S]+account\.role = 'admin'/); assert.match(sql, /DELETE FROM user_business_route_authorizations[\s\S]+account\.role = 'admin'/); assert.match(sql, /UPDATE leader_task_summary_subscriptions subscription[\s\S]+enabled = false[\s\S]+account\.role = 'admin'/); assert.match(sql, /UPDATE leader_task_summary_deliveries delivery[\s\S]+delivery_status = 'cancelled'[\s\S]+account\.role = 'admin'/); assert.match(sql, /CREATE OR REPLACE FUNCTION reject_admin_task_principal/); assert.match(sql, /FOR SHARE/); for (const constraint of [ 'tasks_admin_assignee_forbidden', 'tasks_admin_creator_forbidden', 'user_channels_admin_owner_forbidden', 'browser_connections_admin_worker_forbidden', 'user_business_routes_admin_grantee_forbidden', 'leader_task_summary_admin_subscriber_forbidden', 'leader_task_summary_admin_recipient_forbidden' ]) assert.match(sql, new RegExp(constraint)); assert.match(sql, /CREATE OR REPLACE FUNCTION isolate_administrator_from_task_runtime/); assert.match(sql, /AFTER UPDATE OF role ON users/); assert.doesNotMatch(sql, /DELETE FROM tasks/); }); test('AgentBus channel keys and owners are unique so one inbound identity cannot fan out to multiple employees', async () => { const channels = await source('../src/agentbus-channels.ts'); assert.match(channels, /requireAssignableOwner/); assert.match(channels, /requireUniqueAgentBusKey/); assert.match(channels, /pg_advisory_xact_lock/); assert.match(channels, /sha256Text\(agentbusKey\)/); assert.match(channels, /channel_key_conflict/); assert.match(channels, /channel_owner_conflict/); }); test('account lifecycle is administrator-gated and protects passwords, sessions, and the last administrator', async () => { const [auth, server] = await Promise.all([ source('../src/auth.ts'), source('../src/server.ts') ]); assert.match(auth, /export type AuthRole = 'admin' \| 'team_lead' \| 'user'/); assert.match(auth, /role: normalizeRole\(row\.role\)/); assert.match(auth, /argon2\.hash\([^;]+type: argon2\.argon2id/s); assert.match(auth, /self_lockout_forbidden/); assert.match(auth, /last_admin_protected/); assert.match(auth, /UPDATE sessions SET revoked_at = now\(\)/); assert.match(auth, /must_change_password = false/); assert.match(auth, /function validatePassword[\s\S]+if \(!password\)/); assert.doesNotMatch(auth, /password\.length < 12|12—512/); assert.match(auth, /account\.password_reset/); assert.match(auth, /account\.password_changed/); assert.match(auth, /function validateAccountRouting/); assert.match(auth, /admin_erp_account_forbidden/); assert.match(auth, /erp_account_conflict/); assert.match(server, /app\.get\('\/api\/accounts'[\s\S]+requireAdminSession\(request\)/); assert.match(server, /app\.post\('\/api\/accounts'[\s\S]+requireAdminMutationSession\(request\)/); assert.match(server, /app\.get\('\/api\/audit'[\s\S]+requireAdminSession\(request\)/); assert.doesNotMatch(server, /password_change_required|must_change_password|\.min\(12\)/); const publicUser = server.slice(server.indexOf('function publicUser'), server.indexOf('async function loadExternalParser')); assert.doesNotMatch(publicUser, /must_change_password/); assert.doesNotMatch(publicUser, /organization/); }); test('administrators manage employee task-type grants while remaining outside manual intake', async () => { const [auth, tasks, server] = await Promise.all([ source('../src/auth.ts'), source('../src/task-service.ts'), source('../src/server.ts') ]); assert.match(auth, /authorized_business_route_ids: BusinessRouteId\[\]/); assert.match(auth, /async setBusinessRouteAuthorizations\(/); assert.match(auth, /business_authorization_revision_conflict/); assert.match(auth, /account\.business_authorizations_updated/); assert.match(auth, /admin_business_authorization_fixed/); assert.match(auth, /authorized_business_route_ids: role === 'admin' \? \[\] : storedRouteIds/); assert.match(server, /task_types: BUSINESS_ROUTES\.map/); assert.match(server, /app\.put\('\/api\/accounts\/:userId\/business-authorizations'[\s\S]+requireAdminMutationSession\(request\)/); assert.match(tasks, /export function canExecuteBusinessRoute/); assert.match(tasks, /task\.business_authorization_denied/); assert.match(tasks, /business_type_unresolved/); assert.match(tasks, /当前账号未授权“\$\{route\.directive\}”业务,已禁止执行/); assert.match(tasks, /no_parse: true/); assert.match(tasks, /no_plugin_dispatch: true/); assert.match(tasks, /no_erp_write: true/); const createTask = tasks.slice(tasks.indexOf('async createTask('), tasks.indexOf('async ingestMessage(')); assert.match(createTask, /requireBusinessAuthorization\(context, requestedRouteId/); assert.match(createTask, /assertBusinessAuthorizationInTransaction/); const ingestMessage = tasks.slice(tasks.indexOf('async ingestMessage('), tasks.indexOf('async getTask(')); assert.match(ingestMessage, /requireBusinessAuthorization\(context, preflightRouteId/); assert.match(ingestMessage, /assertBusinessAuthorizationInTransaction/); const attachment = tasks.slice( tasks.indexOf('async attachPassengerRosterAttachment('), tasks.indexOf('async createTask(') ); assert.match(attachment, /requireBusinessAuthorization\(context, target\.routeId/); assert.match(attachment, /assertBusinessAuthorizationInTransaction/); for (const transition of ['confirmTask', 'claimForBrowser']) { const start = tasks.indexOf(`async ${transition}(`); assert.notEqual(start, -1); assert.match(tasks.slice(start, start + 8_000), /assertTaskCreatorBusinessAuthorizationInTransaction/); } const parseResult = tasks.slice(tasks.indexOf('async applyParseResult('), tasks.indexOf('async confirmTask(')); assert.match(parseResult, /taskAuthorization\.allowed && shouldAutomaticallyConfirm/); }); test('operations dashboard is leadership-gated, cross-source, business-facing, and separate from normal task authority', async () => { const [tasks, server] = await Promise.all([ source('../src/task-service.ts'), source('../src/server.ts') ]); assert.match(tasks, /canViewOperationsDashboard[\s\S]+return role === 'team_lead'/); assert.match(tasks, /isTaskOwnerRestricted[\s\S]+role === 'team_lead' \|\| role === 'user'/); assert.match(tasks, /async listOperationsDashboard[\s\S]+t\.assigned_user_id IS NOT NULL[\s\S]+t\.source IN \('manual', 'agentbus'\)/); assert.match(tasks, /actorUserId[\s\S]+t\.assigned_user_id = \$\$\{params\.length\}/); assert.match(tasks, /LEFT JOIN users assignee ON assignee\.id = t\.assigned_user_id/); assert.match(tasks, /operations_dashboard_range_too_large/); assert.match(tasks, /businessRouteId\?: string/); assert.match(tasks, /operations_dashboard_business_invalid/); assert.match(tasks, /operations_dashboard_search_scope_too_large/); assert.match(tasks, /function operationsDashboardRouteFromInstruction/); assert.match(tasks, /function operationsDashboardRouteFromOperation/); assert.match(tasks, /if \(search && candidateResult\.rows\.length > 2_000\)/); assert.match(tasks, /OPERATIONS_DASHBOARD_FALLBACK_TYPES/); assert.match(tasks, /dashboard_order_delete/); assert.match(tasks, /dashboard_arrangement_hotel/); assert.match(tasks, /dashboard_passenger_list_import/); assert.match(tasks, /dashboard_order_update/); assert.match(tasks, /const routeMatches = !businessRouteId/); assert.match(tasks, /content_ciphertext[\s\S]+decryptText\(this\.config, row\.content_ciphertext/); assert.match(tasks, /operationsDashboardSearchMatches[\s\S]+projection\.instruction[\s\S]+projection\.result/); assert.match(tasks, /function operationsDashboardLeadershipResultText/); assert.match(tasks, /function operationsDashboardLeadershipInstructionText/); assert.match(tasks, /待跟进/); assert.match(tasks, /未完成/); assert.match(tasks, /containsTechnicalLanguage/); assert.match(tasks, /当前结果需要人工确认/); assert.match(tasks, /timezone\('Asia\/Shanghai', t\.created_at\)/); assert.match(tasks, /days,[\s\S]+businesses,[\s\S]+business_options/); assert.match(tasks, /instructionPreview\.length > 360/); const detailType = tasks.slice( tasks.indexOf('export interface PublicOperationsDashboardTaskDetail'), tasks.indexOf('export interface PublicOperationsDashboardPage') ); assert.match(detailType, /creator: PublicOperationsDashboardActor/); assert.match(detailType, /instructions: PublicOperationsDashboardInstruction\[\]/); assert.match(detailType, /result_summary: string/); assert.doesNotMatch(detailType, /events|stage|operation|parse_response|execution_result|download_url/); const detailMethod = tasks.slice( tasks.indexOf('async getOperationsDashboardTask('), tasks.indexOf('async listAuditEvents(') ); assert.match(detailMethod, /t\.assigned_user_id IS NOT NULL/); assert.match(detailMethod, /t\.source IN \('manual', 'agentbus'\)/); assert.doesNotMatch(detailMethod, /t\.source = 'manual'/); assert.match(detailMethod, /getTaskInputHistory/); assert.match(detailMethod, /instructions,[\s\S]+attachments:/); assert.doesNotMatch(detailMethod, /this\.getTask\(/); assert.match(server, /app\.get\('\/api\/operations-dashboard'[\s\S]+requireLeadershipSession\(request\)/); assert.match(server, /business_route_id: z\.string\(\)\.trim\(\)\.max\(120\)\.optional\(\)/); assert.match(server, /businessRouteId: query\.business_route_id/); assert.match(server, /signal: controller\.signal/); assert.match(server, /app\.get\('\/api\/operations-dashboard\/tasks\/:taskId'[\s\S]+requireLeadershipSession\(request\)/); assert.match(server, /read_only: true/); assert.doesNotMatch(server, /app\.(?:post|put|patch|delete)\('\/api\/operations-dashboard/); }); test('ordinary task access is enforced across reads, mutations, artifacts, events, and browser connections', async () => { const [tasks, server] = await Promise.all([ source('../src/task-service.ts'), source('../src/server.ts') ]); assert.match(tasks, /assigned_user_id = \$4/); assert.match(tasks, /private async lockTaskForAccess/); for (const mutation of ['reparseTaskWithAi', 'confirmTask', 'claimForBrowser', 'recordExecutionResult', 'cancelTask']) { const start = tasks.indexOf(`async ${mutation}(`); assert.notEqual(start, -1, `${mutation} exists`); const body = tasks.slice(start, start + 20_000); assert.match(body, /lockTaskForAccess\(/, `${mutation} uses the task access lock`); } assert.match(tasks, /async getTaskArtifact[\s\S]+assigned_user_id = \$4/); assert.match(tasks, /async eventsSince[\s\S]+t\.assigned_user_id = \$3/); assert.match(tasks, /async getTaskInputHistory[\s\S]+actor_user_id/); assert.match(tasks, /connection\.organization_id = \$1[\s\S]+connection\.user_id = \$2[\s\S]+connection\.connection_id = \$3/); assert.match(tasks, /WHERE browser_connections\.user_id = EXCLUDED\.user_id/); assert.match(tasks, /browser_worker_conflict/); assert.match(tasks, /identity_mismatch/); assert.match(tasks, /erp_account_mismatch/); assert.match(tasks, /task_execution_assignee_mismatch/); assert.match(tasks, /assignee: publicActor\(row\.assignee_id, row\.assignee_username\)/); const confirmation = tasks.slice(tasks.indexOf('async confirmTask('), tasks.indexOf('async claimForBrowser(')); assert.match(confirmation, /assigned_user_id/); assert.match(confirmation, /task_execution_assignee_mismatch/); assert.match(tasks, /i\.actor_user_id IS NOT DISTINCT FROM \$3::uuid/); assert.match(tasks, /private async lockIdempotencyKey/); assert.match(tasks, /pg_advisory_xact_lock/); assert.match(server, /tasks\.listTasksPage[\s\S]+access: contextFor\(session, request\)/); assert.match(server, /tasks\.getTaskArtifact[\s\S]+contextFor\(session, request\)/); assert.match(server, /tasks\.eventsSince\(session\.user\.organizationId, session\.user\.id, since\)/); assert.match(server, /app\.addHook\('preHandler'[\s\S]+isTaskDataPlaneRoute\(request\.routeOptions\.url\)[\s\S]+requireTaskDataPlane\(await getSession\(request\)\)/); assert.match(server, /task_access_forbidden/); }); test('administrators are excluded from task events and plugin result routing', async () => { const [tasks, server, app] = await Promise.all([ source('../src/task-service.ts'), source('../src/server.ts'), source('../../LianSyn-platform/app.js') ]); const eventHistory = tasks.slice(tasks.indexOf('async eventsSince(')); assert.match(eventHistory, /assignedUserId: string/); assert.match(eventHistory, /AND t\.assigned_user_id = \$3/); assert.doesNotMatch(eventHistory, /isTaskOwnerRestricted\(access\?\.role\)/); const eventRoute = server.slice( server.indexOf("app.get('/api/events'"), server.indexOf('app.setErrorHandler') ); assert.match(eventRoute, /event\.owner_user_id !== session\.user\.id/); assert.match(eventRoute, /command\.assigned_user_id !== session\.user\.id/); assert.match(eventRoute, /event: browser-command/); assert.match(eventRoute, /tasks\.eventsSince\(session\.user\.organizationId, session\.user\.id, since\)/); assert.match(eventRoute, /requireTaskSession\(request\)/); const eventStream = app.slice( app.indexOf('function startRemoteEventStream()'), app.indexOf('function cacheRuntimeTask(') ); assert.match(eventStream, /filter\(taskAssignedToCurrentAccount\)/); assert.match(eventStream, /executable_by=me/); assert.match(eventStream, /addEventListener\('browser-command'/); const bridgeListener = app.slice( app.indexOf("window.addEventListener('message'"), app.indexOf('async function parseRawInstruction') ); assert.match(bridgeListener, /TASK_RESULT_CHANGED/); assert.match(bridgeListener, /extensionTaskBelongsToCurrentAccount\(taskId\)/); const resultQueue = app.slice( app.indexOf('async function persistExtensionTaskResult('), app.indexOf('async function reconcileTaskReceipt(') ); assert.match(resultQueue, /if \(!extensionTaskBelongsToCurrentAccount\(taskId\)\) return false/); assert.match(resultQueue, /!extensionTaskBelongsToCurrentAccount\(normalizedTaskId\)/); assert.match(resultQueue, /!knownTask \|\| !taskAssignedToCurrentAccount\(knownTask\)/); }); test('ERP browser claims serialize only the assigned account queue', async () => { const tasks = await source('../src/task-service.ts'); const claim = tasks.slice(tasks.indexOf('async claimForBrowser('), tasks.indexOf('async recordExecutionResult(')); assert.match(claim, /pg_advisory_xact_lock\([\s\S]+erp-account-queue:[\s\S]+context\.organizationId, context\.userId/); assert.doesNotMatch(claim, /SELECT id FROM organizations WHERE id = \$1 FOR UPDATE/); assert.match(claim, /WHERE t\.organization_id = \$1\s+AND t\.assigned_user_id = \$2[\s\S]+a\.status IN \('accepted', 'running'\)/); assert.match(claim, /WHERE organization_id = \$1\s+AND assigned_user_id = \$2\s+AND status = 'confirmed'/); assert.equal((claim.match(/assigned_user_id = \$2/g) || []).length, 2); assert.match(claim, /\[context\.organizationId, context\.userId\]/); }); test('force delete physically removes accessible tasks without the archive state gate', async () => { const [tasks, server] = await Promise.all([ source('../src/task-service.ts'), source('../src/server.ts') ]); const hardDelete = tasks.slice(tasks.indexOf('async hardDeleteTask('), tasks.indexOf('async cancelTask(')); assert.match(hardDelete, /async hardDeleteTasks\(/); assert.match(hardDelete, /AND \(\$3::boolean = false OR assigned_user_id = \$4\)/); assert.match(hardDelete, /DELETE FROM outbox_events[\s\S]+aggregate_id = ANY\(\$2::text\[\]\)/); assert.match(hardDelete, /DELETE FROM tasks[\s\S]+WHERE id = ANY\(\$1::uuid\[\]\)/); assert.match(hardDelete, /task\.hard_deleted/); assert.match(hardDelete, /assigned_user_id: assignedUserId/); assert.match(hardDelete, /this\.notifyBrowserCommand\(command\)/); assert.match(hardDelete, /this\.artifactStore\.cleanup\(outcome\.artifacts\)/); assert.doesNotMatch(hardDelete, /task_archive_blocked|正在处理或等待 ERP 执行,不能归档/); const bulkDeleteRoute = server.slice( server.indexOf("app.post('/api/tasks/bulk-delete'"), server.indexOf("app.post('/api/tasks/bulk-archive'") ); const singleDeleteRoute = server.slice( server.indexOf("app.delete('/api/tasks/:taskId'"), server.indexOf("app.post('/api/tasks/:taskId/archive'") ); assert.match(bulkDeleteRoute, /tasks\.hardDeleteTasks/); assert.match(singleDeleteRoute, /tasks\.hardDeleteTask/); assert.doesNotMatch(`${bulkDeleteRoute}\n${singleDeleteRoute}`, /tasks\.archiveTask|tasks\.archiveTasks/); }); test('operator UI exposes role-aware accounts, executive drill-through, archive, and explicit permanent deletion', async () => { const [app, index, retention] = await Promise.all([ source('../../LianSyn-platform/app.js'), source('../../LianSyn-platform/index.html'), source('../src/retention.ts') ]); assert.match(index, /href="\/accounts"/); assert.match(index, /href="\/audit"/); assert.match(index, /href="\/operations-dashboard"/); assert.match(index, /id="passwordChangeForm"/); assert.match(index, /id="accountForm"/); assert.match(index, /id="accountErpAccount"/); assert.match(index, /id="channelOwnerUserId"/); assert.doesNotMatch(index, /accountMustChangePassword|首次登录必须修改密码|minlength="12"|12—512/); assert.match(index, /id="accountAuthorizationPanel"/); assert.match(index, /id="accountAuthorizationTypes"/); assert.match(index, /id="accountAuthorizationSave"/); assert.match(index, /value="team_lead">组长/); assert.match(index, /id="operationsDashboardFilters"/); assert.match(index, /id="operationsDashboardBusiness"/); assert.match(index, /id="operationsDashboardBusinesses"/); assert.match(index, /任务类型排名/); assert.match(index, /员工操作任务排名/); assert.match(index, /员工名称/); assert.match(index, /class="operations-dashboard-table"/); assert.match(index, /员工名称、原始输入或最终输出/); assert.match(index, /id="operationsDashboardRangePresets"/); assert.match(index, /id="operationsDashboardRefresh"/); assert.match(index, /任务操作明细/); assert.match(index, /id="operationsDashboardDetail"/); assert.doesNotMatch(index, /平台运行全景|operations-dashboard-hero|OPERATIONS OVERVIEW|BUSINESS TRACE|指令操作历史/); assert.match(index, /id="historyArchiveInput"/); assert.match(index, /id="historyArchiveSelectedButton"/); assert.match(index, /id="historyDeleteSelectedButton"[^>]*>强制删除所选]*>强制删除任务 Number\(right\.total/); assert.doesNotMatch(app, /完成率|operationsDashboardCompletionRate|operationsDashboardDays/); const rankScaleSource = app.slice( app.indexOf('function operationsDashboardRankScale('), app.indexOf('function operationsDashboardRankBar(') ); const rankScale = Function(`${rankScaleSource}\nreturn operationsDashboardRankScale;`)() as (maximum: number) => number; assert.equal(rankScale(0), 1); assert.equal(rankScale(1), 2); assert.equal(rankScale(43), 50); assert.equal(rankScale(100), 120); assert.equal(rankScale(359), 400); assert.match(app, /function operationsDashboardReadableResult/); assert.match(app, /function operationsDashboardReadableInput/); assert.match(app, /原始输入/); assert.match(app, /最终输出/); const dashboardTaskRenderer = app.slice( app.indexOf('function renderOperationsDashboardTasks()'), app.indexOf('function renderOperationsDashboard()') ); assert.match(dashboardTaskRenderer, /task\.creator\.username/); assert.match(dashboardTaskRenderer, /task\.created_at/); assert.match(dashboardTaskRenderer, /task\.business_route_label/); assert.match(dashboardTaskRenderer, /task\.instruction_preview/); assert.match(dashboardTaskRenderer, /operationsDashboardReadableInput\(task\.instruction_preview/); assert.match(dashboardTaskRenderer, /operationsDashboardReadableResult\(task\.result_summary/); assert.doesNotMatch(dashboardTaskRenderer, /记录号|task\.task_id\}`/); const dashboardDetailRenderer = app.slice( app.indexOf('function renderOperationsDashboardDetail()'), app.indexOf('async function syncOperationsDashboard()') ); assert.match(dashboardDetailRenderer, /人员/); assert.match(dashboardDetailRenderer, /原始输入/); assert.match(dashboardDetailRenderer, /最终输出/); assert.match(dashboardDetailRenderer, /operationsDashboardReadableResult/); assert.doesNotMatch(dashboardDetailRenderer, /任务生命周期|处理结果与技术上下文|renderTaskLifecycle|JSON\.stringify|task\.stage|parse_response|operation:/); assert.match(app, /\/api\/tasks\/\$\{encodeURIComponent\(taskId\)\}\/archive/); assert.match(app, /\/api\/tasks\/\$\{encodeURIComponent\(taskId\)\}\/restore/); assert.match(app, /method: 'DELETE'/); assert.match(app, /sendToExtension\('DELETE_TASK'/); assert.match(app, /selectedTasks\.filter\(taskAssignedToCurrentAccount\)/); assert.match(app, /command\?\.target_user_id !== authUser\?\.id/); assert.match(app, /此操作不受“正在处理”或“等待 ERP 执行”状态限制/); assert.match(retention, /SET archived_at = now\(\)/); assert.doesNotMatch(retention, /DELETE FROM tasks/); assert.doesNotMatch(retention, /DELETE FROM audit_events/); }); test('account authorization editor uses a scroll-safe open layout without overriding the closed account list', async () => { const [app, index, styles] = await Promise.all([ source('../../LianSyn-platform/app.js'), source('../../LianSyn-platform/index.html'), source('../../LianSyn-platform/styles.css') ]); const renderStart = app.indexOf('function renderAccountAuthorizationPanel()'); const renderEnd = app.indexOf('function openAccountAuthorizationEditor(', renderStart); const renderSource = app.slice(renderStart, renderEnd); assert.match(renderSource, /const isOpen = Boolean\(account && account\.role !== 'admin'\)/); assert.match(renderSource, /classList\.toggle\('is-authorizing', isOpen\)/); assert.match(renderSource, /if \(!isOpen\)/); const genericLayout = styles.indexOf('.channels-page .channel-panel {'); const openLayout = styles.indexOf('.channels-page .channel-panel.account-panel.is-authorizing {'); assert.ok(genericLayout >= 0, 'generic management-page layout is present'); assert.ok(openLayout > genericLayout, 'account open-state layout follows the generic layout in the cascade'); const openLayoutSource = styles.slice(openLayout, styles.indexOf('}', openLayout) + 1); assert.match(openLayoutSource, /height:\s*max-content/); assert.match(openLayoutSource, /grid-template-rows:\s*auto auto auto auto auto/); assert.match(openLayoutSource, /overflow:\s*visible/); assert.doesNotMatch(styles, /\.account-panel\s*\{\s*grid-template-rows:/); assert.match(index, /styles\.css\?v=20260908-leader-webhook-1/); assert.match(index, /app\.js\?v=20260908-leader-webhook-1/); });