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 { randomUUID } from "node:crypto"; import { afterEach, describe, expect, it } from "vitest"; import { RegistrationError, RegistrationService, type RegistrationTransactionEvent, } 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-28T06:00:00.000Z"); const privacyNoticeVersion = "p0a-notice-v1"; const roots: string[] = []; const services: RegistrationService[] = []; interface Snapshot { challenges: number; consents: number; credits: number; inviteUsedCount: number; ledger: number; profiles: number; sessions: number; users: number; } function createHarness(inviteCode = "DADA-WP1-VALID") { const root = mkdtempSync(join(tmpdir(), "dada-wp1-01-")); roots.push(root); const databasePath = join(root, "dada.sqlite3"); const resend = new MockResendAdapter(); const transactionEvents: RegistrationTransactionEvent[] = []; const service = new RegistrationService({ challengePepper: Buffer.alloc(32, 0x31), clock: () => fixedNow, codeGenerator: () => "482913", currentPrivacyNoticeVersion: privacyNoticeVersion, databasePath, inviteCodeGenerator: () => inviteCode, invitePepper: Buffer.alloc(32, 0x32), onTransaction: (event) => transactionEvents.push(event), resend, sessionPepper: Buffer.alloc(32, 0x33), }); services.push(service); return { databasePath, resend, service, transactionEvents }; } function withDatabase(databasePath: string, operation: (database: any) => T): T { const database = new Database(databasePath); try { return operation(database); } finally { database.close(); } } function seedOccupiedSlots(databasePath: string, count: number) { withDatabase(databasePath, (database) => { const insert = database.prepare(` INSERT INTO users ( user_id, normalized_email, role, status, counts_toward_stage_limit, registration_id, created_at ) VALUES (?, ?, 'user', 'active', 1, ?, ?) `); for (let index = 0; index < count; index += 1) { insert.run(randomUUID(), `occupied-${index}@example.invalid`, randomUUID(), fixedNow - 1_000); } }); } function snapshot(databasePath: string): Snapshot { return withDatabase(databasePath, (database) => ({ challenges: database.prepare("SELECT COUNT(*) AS count FROM email_challenges").get().count, consents: database.prepare("SELECT COUNT(*) AS count FROM privacy_consents").get().count, credits: database.prepare("SELECT COUNT(*) AS count FROM credit_accounts").get().count, inviteUsedCount: database.prepare("SELECT COALESCE(SUM(used_count), 0) AS count FROM invite_codes").get().count, ledger: database.prepare("SELECT COUNT(*) AS count FROM credit_ledger").get().count, profiles: database.prepare("SELECT COUNT(*) AS count FROM user_profiles").get().count, sessions: database.prepare("SELECT COUNT(*) AS count FROM sessions").get().count, users: database.prepare("SELECT COUNT(*) AS count FROM users").get().count, })); } function writeEvidence(relativeDirectory: string, file: string, value: unknown) { const directory = process.env[relativeDirectory]; 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-AUTH-001-valid-register", () => { it("commits the account, invite use, initial credit, consent and one 30-day session once", async () => { const harness = createHarness(); const invite = harness.service.createInvite({ expiresAt: fixedNow + 86_400_000, maxUses: 3 }); seedOccupiedSlots(harness.databasePath, 9); const before = snapshot(harness.databasePath); const sent = await harness.service.sendRegistrationCode({ email: "new-user@example.invalid", inviteCode: invite.code, }); const code = harness.resend.readLatestCode("new-user@example.invalid"); expect(code).toBe("482913"); expect(sent).toMatchObject({ status: "verification_sent" }); const request = { code, creatorName: "Dada Creator", idempotencyKey: "wp1-valid-register-idempotency-key-0001", privacyConsentAccepted: true, privacyNoticeVersion, registrationId: sent.registrationId, socialId: "@@dada_creator", }; const completed = harness.service.completeRegistration(request); const replayed = harness.service.completeRegistration(request); const session = harness.service.readUserSession(completed.sessionToken); const after = snapshot(harness.databasePath); expect(completed).toMatchObject({ credits: { availableBalance: 10, reservedBalance: 0 }, sessionExpiresAt: fixedNow + 30 * 86_400_000, status: "registered", user: { creatorName: "Dada Creator", role: "user", socialId: "@dada_creator", status: "active" }, }); expect(replayed).toEqual(completed); expect(session).toMatchObject({ audience: "user", userId: completed.user.userId }); expect(after).toEqual({ challenges: before.challenges + 1, consents: before.consents + 1, credits: before.credits + 1, inviteUsedCount: before.inviteUsedCount + 1, ledger: before.ledger + 1, profiles: before.profiles + 1, sessions: before.sessions + 1, users: before.users + 1, }); const stored = withDatabase(harness.databasePath, (database) => ({ challenge: database.prepare("SELECT code_hmac, consumed_at FROM email_challenges").get(), ledger: database.prepare("SELECT entry_type, amount, available_before, available_after, reserved_before, reserved_after FROM credit_ledger").get(), session: database.prepare("SELECT token_digest, audience, revoked_at FROM sessions").get(), })); expect(stored.challenge.code_hmac).not.toContain(code); expect(stored.challenge.consumed_at).toBe(fixedNow); expect(stored.ledger).toEqual({ amount: 10, available_after: 10, available_before: 0, entry_type: "registration_grant", reserved_after: 0, reserved_before: 0, }); expect(stored.session).toMatchObject({ audience: "user", revoked_at: null }); expect(stored.session.token_digest).not.toBe(completed.sessionToken); writeEvidence("DADA_EVIDENCE_DIR_AUTH_VALID", "request.json", { operation: ["REGISTER_SEND", "REGISTER_COMPLETE", "AUTH_SESSION"], privacy_notice_version: privacyNoticeVersion, sensitive_fields: "redacted", }); writeEvidence("DADA_EVIDENCE_DIR_AUTH_VALID", "response.json", { audience: session?.audience, available_balance: completed.credits.availableBalance, reserved_balance: completed.credits.reservedBalance, session_days: 30, status: completed.status, }); writeEvidence("DADA_EVIDENCE_DIR_AUTH_VALID", "db-diff.json", { after, before, plaintext_secret_fields: 0 }); }); }); describe("TDD-WP1-AUTH-002-invalid-invite", () => { it.each(["expired", "disabled", "exhausted", "not_found"] as const)( "rejects %s before creating a challenge or calling Resend", async (scenario) => { const harness = createHarness(`DADA-WP1-${scenario.toUpperCase()}`); const invite = harness.service.createInvite({ expiresAt: fixedNow + 86_400_000, maxUses: 1 }); withDatabase(harness.databasePath, (database) => { if (scenario === "expired") database.prepare("UPDATE invite_codes SET expires_at = ?").run(fixedNow - 1); if (scenario === "disabled") database.prepare("UPDATE invite_codes SET status = 'disabled'").run(); if (scenario === "exhausted") database.prepare("UPDATE invite_codes SET used_count = max_uses").run(); }); const before = snapshot(harness.databasePath); const expectedReason = scenario === "not_found" ? "invite_not_found" : `invite_${scenario}`; await expect( harness.service.sendRegistrationCode({ email: "rejected-user@example.invalid", inviteCode: scenario === "not_found" ? `${invite.code}-missing` : invite.code, }), ).rejects.toMatchObject({ code: "REGISTRATION_REJECTED", reason: expectedReason }); expect(snapshot(harness.databasePath)).toEqual(before); expect(harness.resend.calls).toEqual([]); writeEvidence("DADA_EVIDENCE_DIR_AUTH_INVALID", `${scenario}-response.json`, { code: "REGISTRATION_REJECTED", field: "invite_code", reason: expectedReason, }); }, ); it("writes the aggregate zero-side-effect evidence", () => { writeEvidence("DADA_EVIDENCE_DIR_AUTH_INVALID", "db-diff.json", { challenge_delta: 0, consent_delta: 0, credit_delta: 0, invite_used_count_delta: 0, session_delta: 0, user_delta: 0, }); writeEvidence("DADA_EVIDENCE_DIR_AUTH_INVALID", "external-calls.json", { resend_calls: 0 }); }); }); describe("TDD-WP1-AUTH-001-final-recheck-race", () => { it.each(["exhausted", "disabled", "expired", "stage_limit"] as const)( "rechecks %s under BEGIN IMMEDIATE and replays the same failure", async (scenario) => { const harness = createHarness(`DADA-WP1-RACE-${scenario.toUpperCase()}`); const invite = harness.service.createInvite({ expiresAt: fixedNow + 86_400_000, maxUses: 1 }); seedOccupiedSlots(harness.databasePath, 9); const sent = await harness.service.sendRegistrationCode({ email: "race-user@example.invalid", inviteCode: invite.code, }); const code = harness.resend.readLatestCode("race-user@example.invalid"); withDatabase(harness.databasePath, (database) => { if (scenario === "exhausted") database.prepare("UPDATE invite_codes SET used_count = max_uses").run(); if (scenario === "disabled") database.prepare("UPDATE invite_codes SET status = 'disabled'").run(); if (scenario === "expired") database.prepare("UPDATE invite_codes SET expires_at = ?").run(fixedNow - 1); if (scenario === "stage_limit") { database.prepare(` INSERT INTO users ( user_id, normalized_email, role, status, counts_toward_stage_limit, registration_id, created_at ) VALUES (?, ?, 'user', 'active', 1, ?, ?) `).run(randomUUID(), "tenth-user@example.invalid", randomUUID(), fixedNow); } }); const before = snapshot(harness.databasePath); const request = { code, creatorName: "Race User", idempotencyKey: `wp1-race-idempotency-key-${scenario}-0001`, privacyConsentAccepted: true, privacyNoticeVersion, registrationId: sent.registrationId, socialId: "@race_user", }; const expectedReason = scenario === "stage_limit" ? "stage_limit_reached" : `invite_${scenario}`; let first: RegistrationError | undefined; let second: RegistrationError | undefined; try { harness.service.completeRegistration(request); } catch (error) { first = error as RegistrationError; } try { harness.service.completeRegistration(request); } catch (error) { second = error as RegistrationError; } expect(first).toMatchObject({ code: "REGISTRATION_REJECTED", reason: expectedReason }); expect(second).toMatchObject({ code: first?.code, reason: first?.reason }); expect(snapshot(harness.databasePath)).toEqual(before); expect(harness.transactionEvents.filter((event) => event.operation === "registration_complete")) .toEqual(expect.arrayContaining([ expect.objectContaining({ mode: "BEGIN IMMEDIATE", outcome: "rejected" }), expect.objectContaining({ mode: "BEGIN IMMEDIATE", outcome: "idempotent_replay" }), ])); writeEvidence("DADA_EVIDENCE_DIR_AUTH_RACE", `${scenario}-response.json`, { code: first?.code, reason: first?.reason, retry_code: second?.code, retry_reason: second?.reason, }); writeEvidence("DADA_EVIDENCE_DIR_AUTH_RACE", `${scenario}-db-diff.json`, { after: snapshot(harness.databasePath), before }); }, ); it("writes the aggregate transaction evidence", () => { writeEvidence("DADA_EVIDENCE_DIR_AUTH_RACE", "transaction-trace.json", { business_side_effects: 0, failure_replay: "stable", transaction_mode: "BEGIN IMMEDIATE", }); }); });