import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { DatabaseSync } from "node:sqlite"; import test from "node:test"; import { AUDIT_PUBLIC_BETA_ACCESS_FULFILLMENT_SQL, FULFILL_ACCESS_REQUESTS_BY_PUBLIC_BETA_SQL, PUBLIC_BETA_ACCESS_RESPONSE, } from "../db/access-requests.ts"; import { REQUIRED_PUBLIC_BETA_P0_KEYS } from "../db/launch-gates.ts"; function createDatabase() { const db = new DatabaseSync(":memory:"); db.exec(` 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, status TEXT NOT NULL, admin_response TEXT, resolved_by TEXT, invitation_grant_id TEXT, resolved_at TEXT, updated_at TEXT NOT NULL ); CREATE TABLE audit_events ( id TEXT PRIMARY KEY, actor_id TEXT NOT NULL, action TEXT NOT NULL, target_type TEXT NOT NULL, target_id TEXT NOT NULL, reason TEXT NOT NULL, before_json TEXT, after_json TEXT, correlation_id TEXT NOT NULL, created_at TEXT NOT NULL ); INSERT INTO beta_access_requests VALUES ('access_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'requested', NULL, NULL, NULL, NULL, '2026-08-12T00:00:00.000Z'), ('access_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', 'declined', '此前已拒绝', 'admin-old', NULL, '2026-08-11T00:00:00.000Z', '2026-08-11T00:00:00.000Z'); INSERT INTO beta_programs VALUES ('beta_open', 'active', '2026-08-12T00:00:00.000Z', NULL); `); return db; } function reconcile(db, now = "2026-08-12T12:00:00.000Z") { const actor = "admin-public-beta"; const correlation = "corr-public-beta"; return [ Number(db.prepare(FULFILL_ACCESS_REQUESTS_BY_PUBLIC_BETA_SQL).run( PUBLIC_BETA_ACCESS_RESPONSE, actor, now, ).changes), Number(db.prepare(AUDIT_PUBLIC_BETA_ACCESS_FULFILLMENT_SQL).run( actor, PUBLIC_BETA_ACCESS_RESPONSE, correlation, now, ).changes), ]; } test("fulfills pending requests only after active public beta has complete P0 evidence", () => { const db = createDatabase(); for (const key of REQUIRED_PUBLIC_BETA_P0_KEYS.slice(0, -1)) { db.prepare("INSERT INTO launch_gates VALUES (?, 'P0', 'passed', 'owner', 'verified', ?)") .run(key, `https://evidence.example.test/${key}`); } assert.deepEqual(reconcile(db), [0, 0]); assert.equal(db.prepare("SELECT status FROM beta_access_requests WHERE id LIKE 'access_a%'").get().status, "requested"); const lastKey = REQUIRED_PUBLIC_BETA_P0_KEYS.at(-1); db.prepare("INSERT INTO launch_gates VALUES (?, 'P0', 'passed', 'owner', 'verified', ?)") .run(lastKey, `https://evidence.example.test/${lastKey}`); assert.deepEqual(reconcile(db), [1, 1]); assert.deepEqual( { ...db.prepare("SELECT status, admin_response, resolved_by, invitation_grant_id FROM beta_access_requests WHERE id LIKE 'access_a%'").get() }, { status: "approved", admin_response: PUBLIC_BETA_ACCESS_RESPONSE, resolved_by: "admin-public-beta", invitation_grant_id: null, }, ); assert.equal(db.prepare("SELECT status FROM beta_access_requests WHERE id LIKE 'access_b%'").get().status, "declined"); const audit = db.prepare("SELECT action, target_id, after_json FROM audit_events").get(); assert.equal(audit.action, "beta_access.fulfilled_by_public_beta"); assert.equal(audit.target_id, "access_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); assert.equal(JSON.parse(audit.after_json).adminResponse, PUBLIC_BETA_ACCESS_RESPONSE); assert.deepEqual(reconcile(db, "2026-08-12T12:01:00.000Z"), [0, 0]); db.close(); }); test("wires reconciliation into both ways public beta can become open", async () => { const [repository, billingPage, adminPage] = await Promise.all([ readFile(new URL("../db/repository.ts", 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"), ]); const fulfillmentUses = repository.match(/FULFILL_ACCESS_REQUESTS_BY_PUBLIC_BETA_SQL/g) ?? []; const auditUses = repository.match(/AUDIT_PUBLIC_BETA_ACCESS_FULFILLMENT_SQL/g) ?? []; assert.equal(fulfillmentUses.length, 3); // one import plus setPublicBeta and updateLaunchGate assert.equal(auditUses.length, 3); assert.match(billingPage, /request\.admin_response/); assert.match(adminPage, /request\.admin_response/); });