import { randomUUID } from "node:crypto"; import { createRequire } from "node:module"; import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { RegistrationService } from "../../apps/api/src/registration.js"; import { MockResendAdapter } from "../../apps/api/src/resend-adapter.js"; const requireFromApi = createRequire(new URL("../../apps/api/package.json", import.meta.url)); const Database = requireFromApi("better-sqlite3"); const fixedNow = Date.parse("2026-07-28T09:00:00.000Z"); const roots: string[] = []; const services: RegistrationService[] = []; function createHarness() { const root = mkdtempSync(join(tmpdir(), "dada-wp1-03-slot-")); roots.push(root); const databasePath = join(root, "dada.sqlite3"); const resend = new MockResendAdapter(); const service = new RegistrationService({ challengePepper: Buffer.alloc(32, 0x71), clock: () => fixedNow, codeGenerator: () => "731905", currentPrivacyNoticeVersion: "p0a-registration-notice-v1", databasePath, inviteCodeGenerator: () => `DADA-SLOT-${randomUUID()}`, invitePepper: Buffer.alloc(32, 0x72), resend, sessionPepper: Buffer.alloc(32, 0x73), }); services.push(service); return { databasePath, resend, service }; } function withDatabase(databasePath: string, operation: (database: any) => T): T { const database = new Database(databasePath); try { return operation(database); } finally { database.close(); } } function seedSubject( databasePath: string, index: number, role: "user" | "super_admin", status: "active" | "suspended" | "deleted", ) { withDatabase(databasePath, (database) => { database.prepare(` INSERT INTO users ( user_id, normalized_email, role, status, counts_toward_stage_limit, registration_id, created_at ) VALUES (?, ?, ?, ?, ?, ?, ?) `).run( randomUUID(), `slot-fixture-${role}-${status}-${index}@example.invalid`, role, status, role === "user" ? 1 : 0, randomUUID(), fixedNow - 1_000, ); }); } function writeEvidence(file: string, value: unknown) { const directory = process.env.DADA_EVIDENCE_DIR_SLOT; if (!directory) return; mkdirSync(directory, { recursive: true }); writeFileSync(resolve(directory, file), `${JSON.stringify(value, null, 2)}\n`); } afterEach(() => { for (const service of services.splice(0)) service.close(); for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true }); }); describe("TDD-WP1-SLOT-001-stage-limit", () => { it("counts active and suspended users while excluding deleted users and multiple super_admins", async () => { const harness = createHarness(); for (let index = 0; index < 8; index += 1) seedSubject(harness.databasePath, index, "user", "active"); seedSubject(harness.databasePath, 8, "user", "suspended"); seedSubject(harness.databasePath, 9, "user", "deleted"); seedSubject(harness.databasePath, 10, "super_admin", "active"); seedSubject(harness.databasePath, 11, "super_admin", "active"); const invite = harness.service.createInvite({ expiresAt: fixedNow + 86_400_000, maxUses: 3 }); const tenth = await harness.service.sendRegistrationCode({ email: "stage-tenth@example.invalid", inviteCode: invite.code, }); const completed = harness.service.completeRegistration({ code: harness.resend.readLatestCode("stage-tenth@example.invalid"), creatorName: "Tenth User", idempotencyKey: "wp1-03-stage-tenth-complete-00000001", privacyConsentAccepted: true, privacyNoticeVersion: "p0a-registration-notice-v1", registrationId: tenth.registrationId, socialId: "@stage_tenth", }); expect(completed.status).toBe("registered"); await expect(harness.service.sendRegistrationCode({ email: "stage-eleventh@example.invalid", inviteCode: invite.code, })).rejects.toMatchObject({ reason: "stage_limit_reached" }); const counts = withDatabase(harness.databasePath, (database) => ({ active_and_suspended_users: database.prepare(` SELECT COUNT(*) AS count FROM users WHERE role = 'user' AND status IN ('active', 'suspended') `).get().count, deleted_users: database.prepare("SELECT COUNT(*) AS count FROM users WHERE role = 'user' AND status = 'deleted'").get().count, super_admins: database.prepare("SELECT COUNT(*) AS count FROM users WHERE role = 'super_admin'").get().count, })); expect(counts).toEqual({ active_and_suspended_users: 10, deleted_users: 1, super_admins: 2 }); writeEvidence("response.json", { eleventh: "stage_limit_reached", tenth: completed.status }); writeEvidence("db-diff.json", { ...counts, failed_invite_use_delta: 0, failed_user_delta: 0 }); }); it("rechecks capacity after challenge issuance under BEGIN IMMEDIATE", async () => { const harness = createHarness(); for (let index = 0; index < 9; index += 1) seedSubject(harness.databasePath, index, "user", "active"); const invite = harness.service.createInvite({ expiresAt: fixedNow + 86_400_000, maxUses: 2 }); const sent = await harness.service.sendRegistrationCode({ email: "stage-race@example.invalid", inviteCode: invite.code, }); seedSubject(harness.databasePath, 9, "user", "suspended"); expect(() => harness.service.completeRegistration({ code: harness.resend.readLatestCode("stage-race@example.invalid"), creatorName: "Race User", idempotencyKey: "wp1-03-stage-race-complete-000000001", privacyConsentAccepted: true, privacyNoticeVersion: "p0a-registration-notice-v1", registrationId: sent.registrationId, socialId: "@stage_race", })).toThrowError(expect.objectContaining({ reason: "stage_limit_reached" })); const state = withDatabase(harness.databasePath, (database) => ({ consents: database.prepare("SELECT COUNT(*) AS count FROM privacy_consents").get().count, invite_used: database.prepare("SELECT used_count AS count FROM invite_codes WHERE invite_id = ?").get(invite.inviteId).count, sessions: database.prepare("SELECT COUNT(*) AS count FROM sessions").get().count, users: database.prepare("SELECT COUNT(*) AS count FROM users WHERE role = 'user'").get().count, })); expect(state).toEqual({ consents: 0, invite_used: 0, sessions: 0, users: 10 }); writeEvidence("concurrency-trace.json", { final_recheck: "stage_limit_reached", mode: "BEGIN IMMEDIATE", side_effects: state, }); }); });