import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const migration = readFileSync( new URL("../supabase/migrations/20260805010000_reconcile_admin_redemption_audit.sql", import.meta.url), "utf8", ); const auth = readFileSync(new URL("../src/lib/admin/auth.ts", import.meta.url), "utf8"); const authPolicy = readFileSync(new URL("../src/lib/admin/auth-policy.ts", import.meta.url), "utf8"); const adminUser = readFileSync(new URL("../src/lib/supabase/admin.ts", import.meta.url), "utf8"); const codesRoute = readFileSync(new URL("../src/app/api/admin/codes/route.ts", import.meta.url), "utf8"); const codeRoute = readFileSync(new URL("../src/app/api/admin/codes/[id]/route.ts", import.meta.url), "utf8"); const providers = readFileSync(new URL("../src/lib/admin/providers.ts", import.meta.url), "utf8"); const adminLayout = readFileSync(new URL("../src/app/admin/layout.tsx", import.meta.url), "utf8"); const adminApp = readFileSync(new URL("../src/components/admin/admin-app.tsx", import.meta.url), "utf8"); const adminRootRoute = readFileSync(new URL("../src/app/admin/route.ts", import.meta.url), "utf8"); const readonlyRoutes = ["users", "credit-transactions", "consultations", "audit-logs"].map((resource) => readFileSync(new URL(`../src/app/api/admin/${resource}/route.ts`, import.meta.url), "utf8"), ); const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")); test("admin APIs use persisted Better Auth roles with admin-only boundaries", () => { assert.match(auth, /requireIdentityUser/); assert.match(auth, /getIdentityAuthServices\(\)\.user\.api/); assert.match(authPolicy, /user\.role\.includes\("admin"\)/); assert.doesNotMatch(authPolicy, /viewer/); assert.doesNotMatch(auth, /ADMIN_EMAILS|isAdminEmail/); assert.match(auth, /APP_ENV\?\.trim\(\) === "production"/); assert.match(codesRoute, /requireAdminSession\("write"\)/); assert.match(codeRoute, /requireAdminSession\("write"\)/g); }); test("self-hosted account entry checks only the persisted admin role", () => { const selfHostedBranch = adminUser.slice( adminUser.indexOf('process.env.AUTH_PROVIDER?.trim() === "self-hosted"'), adminUser.indexOf("if (isAdminEmail"), ); assert.match(selfHostedBranch, /queryAdminRows/); assert.match(selfHostedBranch, /select role from identity\.users where id = \$1 limit 1/); assert.match(selfHostedBranch, /role === "admin"/); assert.doesNotMatch(selfHostedBranch, /viewer|isAdminEmail|ADMIN_EMAILS/); assert.match(auth, /authorizeAdminAccess\(user, access\)/); }); test("admin navigation exposes payment and package resources", () => { assert.match(adminApp, /name: "payments", list: "\/admin\/payments", meta: \{ label: "支付管理"/); assert.match(adminApp, /name: "packages", list: "\/admin\/packages", meta: \{ label: "套餐管理"/); assert.match(adminApp, /CreditCardOutlined/); assert.match(adminApp, /ShoppingOutlined/); }); test("admin sider replaces logout with a collapsed-aware return-to-chat link", () => { assert.match(adminApp, /ThemedLayout Sider=\{AdminSider\}/); assert.match(adminApp, /ThemedSider/); assert.match(adminApp, /render=\{\(\{ items, collapsed \}\)/); assert.match(adminApp, /\{items\}/); assert.match(adminApp, /ArrowLeftOutlined/); assert.match(adminApp, /\{collapsed \? null : "返回对话"\}<\/Link>/); assert.doesNotMatch(adminApp, /logout\s*[,(}]|authProvider\.logout/); }); test("admin pages and root route are server-gated before rendering or redirecting", () => { assert.match(adminLayout, /await requireAdminSession\("read"\)/); assert.match(adminLayout, /error\.status === 401 \? "\/login" : "\/"/); assert.match(adminLayout, /redirect\(/); assert.match(adminRootRoute, /await requireAdminSession\("read"\)/); assert.match(adminRootRoute, /error\.status === 401 \? "\/login" : "\/"/); assert.match(adminRootRoute, /headers: \{ location: "\/admin\/codes" \}/); }); test("readonly resources cannot be mutated through Refine access control", () => { for (const resource of ["users", "credit-transactions", "consultations", "audit-logs"]) { assert.match(providers, new RegExp(`"${resource}"`)); } assert.match(providers, /readOnlyResources\.has/); assert.match(providers, /此资源只读/); for (const route of readonlyRoutes) { assert.match(route, /export const POST = readonlyAdminMutation/); assert.match(route, /export const PATCH = readonlyAdminMutation/); assert.match(route, /export const DELETE = readonlyAdminMutation/); } }); test("redemption code writes are atomic with append-only redacted audit", () => { assert.match(migration, /create table if not exists audit\.admin_audit_logs/); assert.match(migration, /admin_audit_logs_append_only/); assert.match(migration, /redemption_code\.create/); assert.match(migration, /redemption_code\.update/); assert.match(migration, /redemption_code\.revoke/); assert.match(migration, /before_value is null or not \(before_value \?\| array\['code', 'code_hash', 'token', 'secret', 'key'\]\)/); assert.match(migration, /insert into audit\.admin_audit_logs/); assert.match(migration, /redeemed codes are immutable/); assert.match(migration, /revoked codes are immutable/); assert.match(migration, /v_code\.revoked_at is not null/); assert.match(migration, /'revoked_code'/); assert.match(migration, /set local role service_role|profiles_admin_read/); assert.match(migration, /p_codes is null or jsonb_typeof\(p_codes\) is distinct from 'array'/); assert.match(migration, /admin_verified_actor_email/); }); test("plaintext code is returned only by create and never enters audit snapshots", () => { assert.match(codesRoute, /plainCodes\.map/); assert.match(codesRoute, /code,/); assert.doesNotMatch(codeRoute, /codeHash|code_hash|plainCodes/); const snapshot = migration.match(/create or replace function public\.admin_redemption_code_snapshot[\s\S]*?revoke all on function/); assert.ok(snapshot); assert.doesNotMatch(snapshot[0], /code_hash|'code'/); assert.match(snapshot[0], /'mask'/); }); test("Refine dependencies and same-origin admin data provider are present", () => { for (const dependency of ["@refinedev/core", "@refinedev/antd", "@refinedev/nextjs-router", "antd"]) { assert.ok(packageJson.dependencies[dependency], `${dependency} missing`); } assert.match(providers, /const apiBase = "\/api\/admin"/); assert.doesNotMatch(providers, /https?:\/\//); });