import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { DatabaseSync } from "node:sqlite"; import test from "node:test"; import { APPROVE_ACCESS_REQUEST_SQL, CANCEL_ACCESS_REQUEST_SQL, CREATE_ACCESS_CANCELLATION_IDEMPOTENCY_SQL, CREATE_ACCESS_REQUEST_IDEMPOTENCY_SQL, CREATE_ACCESS_REQUEST_SQL, CREATE_ACCESS_RESOLUTION_IDEMPOTENCY_SQL, CREATE_APPROVED_INVITATION_SQL, CREATE_MANUAL_INVITATION_IDEMPOTENCY_SQL, CREATE_MANUAL_INVITATION_SQL, DECLINE_ACCESS_REQUEST_SQL, } from "../db/access-requests.ts"; function createDatabase() { const database = new DatabaseSync(":memory:"); database.exec(` PRAGMA foreign_keys = ON; CREATE TABLE accounts (id TEXT PRIMARY KEY); CREATE TABLE entitlement_grants ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, host_id TEXT, source TEXT NOT NULL, source_ref TEXT, capacity_slots INTEGER, starts_at TEXT NOT NULL, ends_at TEXT, state TEXT NOT NULL, reason TEXT NOT NULL, created_by TEXT NOT NULL, created_at TEXT NOT NULL, revoked_at TEXT ); CREATE TABLE beta_programs ( id TEXT PRIMARY KEY, state TEXT NOT NULL, starts_at TEXT NOT NULL, ends_at TEXT ); CREATE TABLE launch_gates ( key TEXT PRIMARY KEY, priority TEXT NOT NULL, status TEXT NOT NULL, owner TEXT, notes TEXT NOT NULL, evidence_url TEXT ); CREATE TABLE beta_access_requests ( id TEXT PRIMARY KEY, account_id TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'requested', preferred_os TEXT NOT NULL, requested_slots INTEGER NOT NULL DEFAULT 1, use_case TEXT NOT NULL, admin_response TEXT, resolved_by TEXT, invitation_grant_id TEXT, requested_at TEXT NOT NULL, resolved_at TEXT, cancelled_at TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE UNIQUE INDEX idx_beta_access_requests_one_pending ON beta_access_requests (account_id) WHERE status = 'requested'; CREATE TABLE idempotency_records ( scope TEXT NOT NULL, key TEXT NOT NULL, request_hash TEXT NOT NULL, response_json TEXT NOT NULL, status_code INTEGER NOT NULL, expires_at TEXT NOT NULL, created_at TEXT NOT NULL, PRIMARY KEY (scope, key) ); INSERT INTO accounts VALUES ('account_a'), ('account_b'); `); return database; } function createRequest(database, { id, key, account = "account_a", now }) { const scope = `access-request:create:${account}`; const hash = `hash-${key}`; const response = JSON.stringify({ id, account_id: account, status: "requested" }); return [ Number(database.prepare(CREATE_ACCESS_REQUEST_IDEMPOTENCY_SQL).run( scope, key, hash, response, "2026-09-01T00:00:00.000Z", now, account, ).changes), Number(database.prepare(CREATE_ACCESS_REQUEST_SQL).run( id, account, "windows", 1, "从手机继续本地主机上的已有开发任务。", now, scope, key, hash, ).changes), ]; } test("fences one pending beta request and requires account ownership to cancel", () => { const database = createDatabase(); const now = "2026-08-12T12:00:00.000Z"; assert.deepEqual(createRequest(database, { id: "access_1", key: "create-1", now }), [1, 1]); assert.deepEqual(createRequest(database, { id: "access_2", key: "create-2", now }), [0, 0]); const wrongScope = "access-request:cancel:account_b"; assert.deepEqual([ Number(database.prepare(CREATE_ACCESS_CANCELLATION_IDEMPOTENCY_SQL).run( wrongScope, "cancel-wrong", "wrong-hash", "{}", "2026-09-01T00:00:00.000Z", now, "access_1", "account_b", ).changes), Number(database.prepare(CANCEL_ACCESS_REQUEST_SQL).run( now, "access_1", "account_b", wrongScope, "cancel-wrong", "wrong-hash", ).changes), ], [0, 0]); const scope = "access-request:cancel:account_a"; assert.deepEqual([ Number(database.prepare(CREATE_ACCESS_CANCELLATION_IDEMPOTENCY_SQL).run( scope, "cancel-1", "cancel-hash", "{}", "2026-09-01T00:00:00.000Z", now, "access_1", "account_a", ).changes), Number(database.prepare(CANCEL_ACCESS_REQUEST_SQL).run( now, "access_1", "account_a", scope, "cancel-1", "cancel-hash", ).changes), ], [1, 1]); assert.equal(database.prepare("SELECT status FROM beta_access_requests WHERE id = 'access_1'").get().status, "cancelled"); assert.deepEqual(createRequest(database, { id: "access_3", key: "create-3", now }), [1, 1]); database.close(); }); test("approval atomically creates a bounded free invitation while decline creates none", () => { const database = createDatabase(); const now = "2026-08-12T12:00:00.000Z"; assert.deepEqual(createRequest(database, { id: "access_approve", key: "create-a", now }), [1, 1]); const scope = "admin:access-request:resolve"; const key = "resolve-a"; const hash = "resolve-hash-a"; const grantId = "grant_approve"; database.exec("BEGIN IMMEDIATE"); const approved = [ Number(database.prepare(CREATE_ACCESS_RESOLUTION_IDEMPOTENCY_SQL).run( scope, key, hash, "{}", 200, "2026-09-01T00:00:00.000Z", now, "access_approve", ).changes), Number(database.prepare(CREATE_APPROVED_INVITATION_SQL).run( grantId, "access_approve", 2, now, "2026-11-12T12:00:00.000Z", "首批闭测", "admin", "access_approve", scope, key, hash, ).changes), Number(database.prepare(APPROVE_ACCESS_REQUEST_SQL).run( "已开放两台主机。", "admin", grantId, now, "access_approve", scope, key, hash, ).changes), ]; database.exec("COMMIT"); assert.deepEqual(approved, [1, 1, 1]); assert.deepEqual( { ...database.prepare("SELECT status, invitation_grant_id FROM beta_access_requests WHERE id = 'access_approve'").get() }, { status: "approved", invitation_grant_id: grantId }, ); assert.deepEqual( { ...database.prepare("SELECT source, source_ref, capacity_slots, state FROM entitlement_grants WHERE id = ?").get(grantId) }, { source: "admin_exemption", source_ref: "access_approve", capacity_slots: 2, state: "active" }, ); assert.deepEqual([ Number(database.prepare(CREATE_ACCESS_RESOLUTION_IDEMPOTENCY_SQL).run( scope, "resolve-again", "resolve-hash-again", "{}", 200, "2026-09-01T00:00:00.000Z", now, "access_approve", ).changes), Number(database.prepare(DECLINE_ACCESS_REQUEST_SQL).run( "重复处理", "admin", now, "access_approve", scope, "resolve-again", "resolve-hash-again", ).changes), ], [0, 0]); assert.deepEqual(createRequest(database, { id: "access_decline", key: "create-d", account: "account_b", now }), [1, 1]); const declineKey = "resolve-d"; const declineHash = "resolve-hash-d"; assert.deepEqual([ Number(database.prepare(CREATE_ACCESS_RESOLUTION_IDEMPOTENCY_SQL).run( scope, declineKey, declineHash, "{}", 200, "2026-09-01T00:00:00.000Z", now, "access_decline", ).changes), Number(database.prepare(DECLINE_ACCESS_REQUEST_SQL).run( "当前名额有限。", "admin", now, "access_decline", scope, declineKey, declineHash, ).changes), ], [1, 1]); assert.equal(database.prepare("SELECT status FROM beta_access_requests WHERE id = 'access_decline'").get().status, "declined"); assert.equal(database.prepare("SELECT COUNT(*) AS count FROM entitlement_grants").get().count, 1); database.close(); }); test("requires pending requests to be resolved instead of bypassed by a manual invitation", () => { const database = createDatabase(); const now = "2026-08-12T12:00:00.000Z"; assert.deepEqual(createRequest(database, { id: "access_pending", key: "create-p", now }), [1, 1]); const scope = "admin:exemption"; assert.deepEqual([ Number(database.prepare(CREATE_MANUAL_INVITATION_IDEMPOTENCY_SQL).run( scope, "manual-p", "manual-hash-p", "{}", "2026-09-01T00:00:00.000Z", now, "account_a", ).changes), Number(database.prepare(CREATE_MANUAL_INVITATION_SQL).run( "grant_manual_p", "account_a", "grant_manual_p", 1, now, "2026-11-12T12:00:00.000Z", "proactive invitation", "admin", now, scope, "manual-p", "manual-hash-p", ).changes), ], [0, 0]); assert.deepEqual([ Number(database.prepare(CREATE_MANUAL_INVITATION_IDEMPOTENCY_SQL).run( scope, "manual-b", "manual-hash-b", "{}", "2026-09-01T00:00:00.000Z", now, "account_b", ).changes), Number(database.prepare(CREATE_MANUAL_INVITATION_SQL).run( "grant_manual_b", "account_b", "grant_manual_b", 1, now, "2026-11-12T12:00:00.000Z", "proactive invitation", "admin", now, scope, "manual-b", "manual-hash-b", ).changes), ], [1, 1]); assert.deepEqual(createRequest(database, { id: "access_after_invite", key: "create-after-b", account: "account_b", now }), [0, 0]); assert.equal(database.prepare("SELECT COUNT(*) AS count FROM entitlement_grants").get().count, 1); database.close(); }); test("keeps beta access requests authenticated, non-monetary, visible, and migrated", async () => { const [userRoute, adminRoute, userForm, adminActions, billingPage, adminPage, repository, bootstrap, migration, contract] = await Promise.all([ readFile(new URL("../app/api/beta-access/route.ts", import.meta.url), "utf8"), readFile(new URL("../app/api/admin/beta-access/route.ts", import.meta.url), "utf8"), readFile(new URL("../app/dashboard/billing/AccessRequestForm.tsx", import.meta.url), "utf8"), readFile(new URL("../app/admin/AdminActions.tsx", import.meta.url), "utf8"), readFile(new URL("../app/dashboard/billing/page.tsx", import.meta.url), "utf8"), readFile(new URL("../app/admin/page.tsx", import.meta.url), "utf8"), readFile(new URL("../db/repository.ts", import.meta.url), "utf8"), readFile(new URL("../db/bootstrap.ts", import.meta.url), "utf8"), readFile(new URL("../drizzle/0010_windy_toxin.sql", import.meta.url), "utf8"), readFile(new URL("../docs/commercial-contract.md", import.meta.url), "utf8"), ]); assert.match(userRoute, /getCloudViewer/); assert.match(userRoute, /getOrCreateAccount/); assert.match(userRoute, /readJsonMutation/); assert.match(adminRoute, /viewer\.isAdmin/); assert.match(adminRoute, /resolveBetaAccessRequest/); assert.match(userForm, /请勿粘贴令牌、密码、项目代码或私密会话内容/); assert.match(adminActions, /批准并签发免费邀请/); assert.match(billingPage, /申请免费闭测资格/); assert.match(adminPage, /免费闭测申请队列/); assert.match(repository, /beta_access_requests: accessRequests/); assert.match(repository, /source_ref/); assert.match(repository, /access_request_requires_resolution/); assert.match(bootstrap, /0010_windy_toxin/); assert.match(migration, /idx_beta_access_requests_one_pending/); assert.match(contract, /申请时间不构成名额承诺或队列优先级/); }); test("applies the generated access-request migration to an existing base database", async () => { const [base, accessMigration] = await Promise.all([ readFile(new URL("../drizzle/0000_condemned_legion.sql", import.meta.url), "utf8"), readFile(new URL("../drizzle/0010_windy_toxin.sql", import.meta.url), "utf8"), ]); const database = new DatabaseSync(":memory:"); database.exec(base.replaceAll("--> statement-breakpoint", "")); database.exec(accessMigration.replaceAll("--> statement-breakpoint", "")); assert.equal( database.prepare("SELECT COUNT(*) AS count FROM pragma_table_info('beta_access_requests')").get().count, 14, ); assert.equal( database.prepare("SELECT COUNT(*) AS count FROM pragma_index_list('beta_access_requests') WHERE origin = 'c'").get().count, 3, ); database.close(); });