import test from "node:test"; import assert from "node:assert/strict"; import os from "node:os"; import path from "node:path"; import { mkdtemp, rm } from "node:fs/promises"; import { NextRequest } from "next/server"; let runtimeRoot = ""; let data: typeof import("../src/lib/boss-data"); let authCookie = ""; let getAdminAccess: (typeof import("../src/app/api/v1/admin/access/route"))["GET"]; let postAdminAccess: (typeof import("../src/app/api/v1/admin/access/route"))["POST"]; let baseState: Awaited>; async function setup() { if (runtimeRoot) return; runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-admin-company-")); process.env.BOSS_RUNTIME_ROOT = runtimeRoot; process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json"); const [dataModule, authModule, routeModule] = await Promise.all([ import("../src/lib/boss-data.ts"), import("../src/lib/boss-auth.ts"), import("../src/app/api/v1/admin/access/route.ts"), ]); data = dataModule; authCookie = authModule.AUTH_SESSION_COOKIE; getAdminAccess = routeModule.GET; postAdminAccess = routeModule.POST; baseState = structuredClone(await data.readState()); } test.after(async () => { if (runtimeRoot) await rm(runtimeRoot, { recursive: true, force: true }); }); test.beforeEach(async () => { await setup(); const state = structuredClone(baseState); const now = "2026-04-27T14:00:00+08:00"; state.authAccounts = [ { id: "account-owner", account: "owner@platform.com", passwordHash: "secret", displayName: "平台老板", role: "highest_admin", createdAt: now, updatedAt: now, }, { id: "account-worker", account: "worker@acme.com", passwordHash: "secret", displayName: "待分配成员", role: "member", createdAt: now, updatedAt: now, }, ]; state.authSessions = []; state.devices = [ { id: "mac-1", name: "客户 Mac", avatar: "M", account: "worker@acme.com", source: "production", status: "online", projects: [], quota5h: 0, quota7d: 0, lastSeenAt: now, preferredExecutionMode: "cli", capabilities: { gui: { connected: true, lastSeenAt: now }, cli: { connected: true, lastSeenAt: now }, browserAutomation: { connected: false }, computerUse: { connected: false }, }, }, ]; state.accountDeviceGrants = [ { grantId: "grant-device", account: "worker@acme.com", deviceId: "mac-1", permissions: ["device.view"], grantedBy: "owner@platform.com", grantedAt: now, }, ]; state.accountProjectGrants = []; state.accountSkillGrants = []; state.permissionAuditLogs = []; await data.writeState(state); }); async function authedRequest(body?: Record, method = "POST") { const session = await data.createAuthSession({ account: "owner@platform.com", role: "highest_admin", displayName: "平台老板", loginMethod: "password", }); return new NextRequest("http://127.0.0.1:3000/api/v1/admin/access", { method, headers: { "content-type": "application/json", cookie: `${authCookie}=${session.sessionToken}`, }, body: body ? JSON.stringify(body) : undefined, }); } async function adminPost(body: Record) { return postAdminAccess(await authedRequest(body)); } test("highest admin can manage companies and assign accounts and devices", async () => { const createCompany = await adminPost({ action: "upsert_company", companyId: "acme", name: "Acme 客户", ownerAccount: "owner@acme.com", successOwnerAccount: "cs@platform.com", planTier: "enterprise", contractExpiresAt: "2026-12-31T23:59:59+08:00", note: "第一批 To B 客户", }); assert.equal(createCompany.status, 200); const createPayload = await createCompany.json(); assert.equal(createPayload.company.companyId, "acme"); assert.equal(createPayload.company.name, "Acme 客户"); assert.equal(createPayload.company.planTier, "enterprise"); assert.equal(createPayload.company.successOwnerAccount, "cs@platform.com"); assert.equal(createPayload.company.contractExpiresAt, "2026-12-31T23:59:59+08:00"); const assignAccount = await adminPost({ action: "assign_account_company", account: "worker@acme.com", companyId: "acme", }); assert.equal(assignAccount.status, 200); assert.equal((await assignAccount.json()).account.companyId, "acme"); const assignDevice = await adminPost({ action: "assign_device_company", deviceId: "mac-1", companyId: "acme", }); assert.equal(assignDevice.status, 200); assert.equal((await assignDevice.json()).device.companyId, "acme"); const getResponse = await getAdminAccess(await authedRequest(undefined, "GET")); const getPayload = await getResponse.json(); assert.equal(getPayload.companies.some((company: { companyId: string }) => company.companyId === "acme"), true); assert.equal(getPayload.companies.find((company: { companyId: string }) => company.companyId === "acme")?.planTier, "enterprise"); assert.equal(getPayload.accounts.find((account: { account: string }) => account.account === "worker@acme.com")?.companyId, "acme"); assert.equal(getPayload.devices.find((device: { id: string }) => device.id === "mac-1")?.companyId, "acme"); }); test("highest admin can toggle account MFA without exposing the secret in access GET", async () => { const response = await adminPost({ action: "set_account_mfa_required", account: "worker@acme.com", required: true, }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.account.mfaRequired, true); assert.equal(typeof payload.mfaSetupSecret, "string"); assert.equal(payload.account.mfaSecret, undefined); const getResponse = await getAdminAccess(await authedRequest(undefined, "GET")); const getPayload = await getResponse.json(); const account = getPayload.accounts.find((item: { account: string }) => item.account === "worker@acme.com"); assert.equal(account.mfaRequired, true); assert.equal(account.mfaSecret, undefined); }); test("admin access GET returns safe project metadata without chat transcripts", async () => { const state = await data.readState(); const now = "2026-04-27T14:05:00+08:00"; state.projects = [ { id: "project-secret", name: "敏感项目", pinned: false, deviceIds: ["mac-1"], preview: "passwordHash should not leave through admin access", updatedAt: now, lastMessageAt: now, isGroup: false, threadMeta: { projectId: "project-secret", threadId: "thread-secret", threadDisplayName: "敏感线程", folderName: "secret", activityIconCount: 1, updatedAt: now, }, groupMembers: [], createdByAgent: false, collaborationMode: "development", approvalState: "not_required", unreadCount: 0, riskLevel: "low", messages: [ { id: "msg-secret", role: "assistant", author: "线程", body: "passwordHash=secret should stay in project transcript only", createdAt: now, }, ], goals: [], versions: [], }, ]; await data.writeState(state); const response = await getAdminAccess(await authedRequest(undefined, "GET")); assert.equal(response.status, 200); const payload = await response.json(); const project = payload.projects.find((item: { id: string }) => item.id === "project-secret"); assert.equal(project.name, "敏感项目"); assert.deepEqual(project.deviceIds, ["mac-1"]); assert.equal(project.messages, undefined); assert.equal(project.preview, undefined); assert.equal(JSON.stringify(payload.accounts).includes("passwordHash"), false); assert.equal(JSON.stringify(payload.projects).includes("passwordHash"), false); }); test("highest admin can bulk import accounts into a company", async () => { await adminPost({ action: "upsert_company", companyId: "acme", name: "Acme 客户" }); const response = await adminPost({ action: "bulk_import_accounts", companyId: "acme", accounts: [ { account: "pm@acme.com", displayName: "产品负责人", role: "admin", password: "pass-123" }, { account: "dev2@acme.com", displayName: "开发二号", role: "member", password: "pass-456" }, ], }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.imported.length, 2); assert.equal(payload.imported.every((account: { passwordHash?: string }) => account.passwordHash === undefined), true); const state = await data.readState(); assert.deepEqual( state.authAccounts .filter((account) => account.companyId === "acme") .map((account) => account.account) .sort(), ["dev2@acme.com", "pm@acme.com"], ); }); test("highest admin can reclaim a leaving account and clear its grants and sessions", async () => { const workerSession = await data.createAuthSession({ account: "worker@acme.com", role: "member", displayName: "待分配成员", loginMethod: "password", }); const response = await adminPost({ action: "reclaim_account", account: "worker@acme.com", reason: "员工离职", }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.account.status, "disabled"); assert.equal(payload.removedGrants.deviceGrants, 1); const state = await data.readState(); assert.equal(state.authAccounts.find((account) => account.account === "worker@acme.com")?.status, "disabled"); assert.equal(state.accountDeviceGrants.some((grant) => grant.account === "worker@acme.com"), false); assert.equal( state.authSessions.find((session) => session.sessionToken === workerSession.sessionToken)?.revokedAt !== undefined, true, ); assert.equal(state.permissionAuditLogs.at(0)?.action, "account.reclaimed"); });