f4a2ba86ae
Report pages now scroll inside the chat shell lock, and admin product save forks a draft or retires a published plan instead of rejecting with a generic constraint error. Co-authored-by: Cursor <cursoragent@cursor.com>
133 lines
8.4 KiB
TypeScript
133 lines
8.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
const source = (path: string) => readFileSync(new URL(`../${path}`, import.meta.url), "utf8");
|
|
const packagesRoute = source("src/app/api/payment/packages/route.ts");
|
|
const createRoute = source("src/app/api/payment/epay/create/route.ts");
|
|
const statusRoute = source("src/app/api/payment/epay/status/route.ts");
|
|
const notifyRoute = source("src/app/api/payment/epay/notify/route.ts");
|
|
const productsRoute = source("src/app/api/admin/products/route.ts");
|
|
const epaySettingsRoute = source("src/app/api/admin/epay-settings/route.ts");
|
|
const subscriptionsRoute = source("src/app/api/admin/subscriptions/route.ts");
|
|
const featureFlagsRoute = source("src/app/api/admin/feature-flags/route.ts");
|
|
const modelsRoute = source("src/app/api/admin/models/route.ts");
|
|
const modelDiscoveryRoute = source("src/app/api/admin/models/discover/route.ts");
|
|
const modelMutationHandler = source("src/lib/admin/model-mutation-handler.ts");
|
|
const ordersRoute = source("src/app/api/admin/orders/route.ts");
|
|
const codesRoute = source("src/app/api/admin/codes/route.ts");
|
|
const codeRoute = source("src/app/api/admin/codes/[id]/route.ts");
|
|
const codesHelper = source("src/lib/admin/codes.ts");
|
|
const billingOperationsUi = source("src/components/admin/billing-operations-resources.tsx");
|
|
const codesUi = source("src/components/admin/codes-resource.tsx");
|
|
const redemptionAccessMigration = source("supabase/migrations/20260816010000_admin_redemption_admin_access.sql");
|
|
const baseRedemptionMigration = source("supabase/migrations/20260805010000_reconcile_admin_redemption_audit.sql");
|
|
|
|
test("billing.subscriptions only gates new trial and subscription purchases", () => {
|
|
assert.match(packagesRoute, /loadRuntimeFeatureFlags\(\["billing\.subscriptions"\]\)/);
|
|
assert.match(packagesRoute, /subscriptionsEnabled \|\| product\.product_type === "credit_pack"/);
|
|
assert.match(createRoute, /product\.product_type !== "credit_pack"[\s\S]*billing\.subscriptions[\s\S]*BILLING_SUBSCRIPTIONS_DISABLED/);
|
|
assert.ok(
|
|
createRoute.indexOf("BILLING_SUBSCRIPTIONS_DISABLED") < createRoute.indexOf('.from("payment_orders").insert'),
|
|
"the flag must reject subscription orders before insertion",
|
|
);
|
|
});
|
|
|
|
test("existing payment orders remain queryable and settleable when subscriptions are disabled", () => {
|
|
assert.doesNotMatch(statusRoute, /billing\.subscriptions|loadRuntimeFeatureFlags/);
|
|
assert.doesNotMatch(notifyRoute, /billing\.subscriptions|loadRuntimeFeatureFlags/);
|
|
assert.match(statusRoute, /from\("payment_orders"\)/);
|
|
assert.match(notifyRoute, /createEpayNotifyHandler[\s\S]*settle_order/);
|
|
});
|
|
|
|
test("billing and operations writes use the shared ordinary mutation guard", () => {
|
|
assert.match(productsRoute, /requireAdminMutation\(request, permission\)/);
|
|
assert.match(productsRoute, /admin_console_(?:save|publish|delete)_product/);
|
|
assert.match(productsRoute, /admin_delete_product/);
|
|
const productMutationMigration = source("supabase/migrations/20260818010000_admin_product_catalog_mutations.sql");
|
|
assert.match(productMutationMigration, /jsonb_build_object\('productCode'/);
|
|
assert.doesNotMatch(productMutationMigration, /jsonb_build_object\('code'/);
|
|
assert.match(epaySettingsRoute, /requireAdminMutation\(request, "billing\.adjustments\.write"\)/);
|
|
assert.match(epaySettingsRoute, /admin_save_epay_settings/);
|
|
assert.match(subscriptionsRoute, /requireAdminMutation\(request,"billing\.adjustments\.write"\)/);
|
|
assert.match(subscriptionsRoute, /admin_console_adjust_subscription/);
|
|
assert.match(featureFlagsRoute, /requireAdminMutation\(request,"ops\.flags\.write"\)/);
|
|
assert.match(featureFlagsRoute, /admin_console_publish_feature_flag/);
|
|
for (const route of [productsRoute, epaySettingsRoute, subscriptionsRoute, featureFlagsRoute]) {
|
|
assert.doesNotMatch(route, /requireHighRiskAdminMutation/);
|
|
}
|
|
});
|
|
|
|
test("model provider changes and release mutations use the ordinary admin guard", () => {
|
|
assert.match(modelsRoute, /await requireAdminMutation\(request, permission\)/);
|
|
assert.doesNotMatch(modelsRoute, /requireHighRiskAdminMutation/);
|
|
assert.match(modelDiscoveryRoute, /requireAdminMutation\(request,"models\.test"\)/);
|
|
assert.doesNotMatch(modelDiscoveryRoute, /requireHighRiskAdminMutation/);
|
|
assert.match(modelsRoute, /handleAdminModelMutation\(/);
|
|
assert.match(modelMutationHandler, /admin_save_model_provider/);
|
|
assert.match(modelMutationHandler, /admin_publish_model/);
|
|
assert.match(modelMutationHandler, /probeAndRecord[\s\S]*admin_rollback_model/);
|
|
});
|
|
|
|
|
|
test("self-hosted payment catalog uses simple queries and immutable product snapshots", () => {
|
|
assert.doesNotMatch(packagesRoute, /product_entitlements\s*\(/);
|
|
assert.doesNotMatch(createRoute, /product_entitlements\s*\(/);
|
|
assert.match(packagesRoute, /\.from\("billing_products"\)[\s\S]*\.from\("product_entitlements"\)/);
|
|
assert.match(packagesRoute, /entitlementsByProduct/);
|
|
assert.match(createRoute, /\.from\("billing_products"\)[\s\S]*\.from\("product_entitlements"\)/);
|
|
assert.match(createRoute, /oneTimePerUser:\s*product\.one_time_per_user/);
|
|
assert.match(createRoute, /product_snapshot:\s*productSnapshot/);
|
|
});
|
|
|
|
test("order adjustments require permission, version, server audit reason, request id, and the domain RPC", () => {
|
|
assert.match(
|
|
ordersRoute,
|
|
/requireAdminMutation\(\s*request,\s*"billing\.adjustments\.write",?\s*\)/,
|
|
);
|
|
assert.match(ordersRoute, /expectedVersion:\s*z\.number\(\)\.int\(\)\.min\(0\)/);
|
|
assert.doesNotMatch(ordersRoute, /reason:\s*z\.string/);
|
|
assert.match(ordersRoute, /admin_console_adjust_order/);
|
|
assert.match(ordersRoute, /queryAdminRows<AdjustmentRow>/);
|
|
assert.match(ordersRoute, /public\.admin_adjust_order\(/);
|
|
assert.match(ordersRoute, /requestId\(request\)/);
|
|
assert.doesNotMatch(ordersRoute, /createAdminSupabaseClient|\.rpc\(/);
|
|
assert.match(billingOperationsUi, /retry_grant/);
|
|
assert.match(billingOperationsUi, /compensate/);
|
|
assert.match(billingOperationsUi, /record_refund/);
|
|
assert.doesNotMatch(billingOperationsUi, /reauthPermission|邮箱验证码|\/api\/admin\/reauth/);
|
|
assert.match(billingOperationsUi, /不调用支付网关|仅记录账务/);
|
|
});
|
|
|
|
test("redemption-code writes generate server audit reasons and encode JSONB for self-hosted pg", () => {
|
|
assert.match(codesRoute, /await requirePermission\("admin\.access"\)/);
|
|
assert.match(codesRoute, /requireAdminMutation\(\s*request,\s*"admin\.access",?\s*\)/);
|
|
assert.equal((codeRoute.match(/requireAdminMutation\(/g) ?? []).length, 2);
|
|
assert.doesNotMatch(codeRoute, /requireHighRiskAdminMutation/);
|
|
assert.doesNotMatch(codesRoute, /reason:\s*z\.string/);
|
|
assert.doesNotMatch(codeRoute, /reason:\s*z\.string/);
|
|
assert.match(codesRoute, /p_reason:\s*"admin_console_create_redemption_codes"/);
|
|
assert.match(codeRoute, /p_reason:\s*"admin_console_update_redemption_code"/);
|
|
assert.match(codeRoute, /p_reason:\s*"admin_console_revoke_redemption_code"/);
|
|
assert.match(codesHelper, /JSON\.stringify\(input\.p_codes\)/);
|
|
assert.match(codesHelper, /session\.user\.email,[\s\S]*"admin",/);
|
|
assert.doesNotMatch(codesHelper, /session\.roles\[0\]/);
|
|
assert.match(codesHelper, /queryAdminRows<RpcCodeRow>/);
|
|
assert.match(codesHelper, /public\.admin_create_redemption_codes\(/);
|
|
assert.match(codesHelper, /public\.admin_update_redemption_code\(/);
|
|
assert.match(codesHelper, /public\.admin_revoke_redemption_code\(/);
|
|
assert.doesNotMatch(codesHelper, /createAdminSupabaseClient|\.rpc\(|\$\{functionName\}/);
|
|
assert.match(codesUi, /permissions\.includes\("admin\.access"\)/);
|
|
assert.doesNotMatch(codesUi, /reauthPermission|邮箱验证码|\/api\/admin\/reauth/);
|
|
assert.match(codesUi, /onFinish=\{\(values\) => void submitCreate\(values\)\}/);
|
|
assert.match(codesUi, /onFinish=\{\(values\) => void submitEdit\(values\)\}/);
|
|
assert.match(codesUi, /onClick=\{\(\) => void revoke\(record\)\}/);
|
|
assert.doesNotMatch(codesUi, /ConfirmActionModal|pendingCreate|pendingEdit|revokeRecord/);
|
|
assert.match(codesUi, /copyable=\{\{ text: record\.code \?\? "" \}\}/);
|
|
assert.equal((redemptionAccessMigration.match(/admin_has_permission\(p_actor_user_id,'admin\.access'\)/g) ?? []).length, 3);
|
|
assert.match(redemptionAccessMigration, /new\.permission_used := 'admin\.access'/);
|
|
assert.match(baseRedemptionMigration, /admin_verified_actor_email/);
|
|
assert.match(redemptionAccessMigration, /grant execute on function public\.admin_create_redemption_codes/);
|
|
assert.doesNotMatch(redemptionAccessMigration, /billing\.adjustments\.write/);
|
|
});
|