import { readdir, readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; /** * Structural guarantees about email verification and password recovery that no runtime assertion can * make (ADR 0038). * * These read the repository itself, because what matters here is what code *exists* and what depends * on what: that identity never learns an SMTP detail, that no token store was reimplemented * alongside Better Auth's, that a device identity has no route into a human email flow, and that * nothing in a browser bundle can reach any of it. */ const repositoryRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", ".."); async function readTypeScriptFiles( directory: string, ): Promise> { const results: Array<{ path: string; text: string }> = []; const walk = async (current: string): Promise => { for (const entry of await readdir(current, { withFileTypes: true })) { const full = path.join(current, entry.name); if (entry.isDirectory()) { if (entry.name === "node_modules" || entry.name === "dist") { continue; } await walk(full); continue; } if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) { results.push({ path: full, text: await readFile(full, "utf8") }); } } }; await walk(path.join(repositoryRoot, directory)); return results; } /** Strips block comments and whole-line `//` comments: these assertions are about code, and prose * explaining a rule inevitably quotes the token the rule forbids. */ function withoutComments(text: string): string { return text .replaceAll(/\/\*[\s\S]*?\*\//gu, "") .split("\n") .filter((line) => !line.trimStart().startsWith("//")) .join("\n"); } describe("identity email flows stay above the mail transport", () => { it("names no SMTP or provider detail anywhere in the identity feature", async () => { for (const file of await readTypeScriptFiles(path.join("core", "src", "identity"))) { const code = withoutComments(file.text).toLowerCase(); for (const forbidden of [ "nodemailer", "smtpserver", "starttls", "createtransport", "587", "465", ]) { expect(code, `${file.path} names ${forbidden}`).not.toContain(forbidden); } } }); it("reaches the transport only through the provider seam", async () => { const notifications = await readFile( path.join(repositoryRoot, "core", "src", "identity", "notifications.ts"), "utf8", ); // The whole mail surface identity may use: a validated message and a `send`. Not a config, not // a transport, not a credential. expect(notifications).toContain('from "../mail/index.js"'); expect(withoutComments(notifications)).not.toContain("MailProviderConfig"); expect(withoutComments(notifications)).not.toContain("createSmtpMailProvider"); }); }); describe("Better Auth owns every token", () => { it("adds no Ekklesia table, column, or store for a verification or reset token", async () => { const schemas = [ path.join("core", "src", "identity", "schema.ts"), path.join("core", "src", "authorization", "schema.ts"), path.join("core", "src", "devices", "schema.ts"), ]; for (const relative of schemas) { const code = withoutComments( await readFile(path.join(repositoryRoot, relative), "utf8"), ).toLowerCase(); // A parallel token table would be a second expiry clock, a second consumption rule, and a // second thing to get wrong. `ekklesia_core_verification` is Better Auth's own table. expect(code, relative).not.toContain("reset_token"); expect(code, relative).not.toContain("verification_token"); expect(code, relative).not.toContain("password_reset"); } }); it("never hashes, stores, or compares a token itself", async () => { for (const file of await readTypeScriptFiles(path.join("core", "src", "identity"))) { const code = withoutComments(file.text); expect(code, file.path).not.toContain("createHash"); expect(code, file.path).not.toContain("timingSafeEqual"); } }); it("interpolates no token, link, address, or message body into anything it logs", async () => { for (const file of await readTypeScriptFiles(path.join("core", "src", "identity"))) { const code = withoutComments(file.text); for (const call of code.matchAll(/console\.\w+\(([^\n]*)/gu)) { // Fixed prose in a log line is fine; a **substituted value** is what could carry a secret. // Only the interpolations are examined, so "email was not delivered" passes while // `${user.email}` could not. for (const substitution of (call[1] ?? "").matchAll(/\$\{([^}]*)\}/gu)) { const expression = (substitution[1] ?? "").toLowerCase(); for (const forbidden of ["token", "url", "html", "text", "email", "recipient", "body"]) { expect(expression, `${file.path} logs ${forbidden}`).not.toContain(forbidden); } } } } }); }); describe("managed devices have no part in human email identity", () => { it("gives a device no address, password, or verification state", async () => { for (const file of await readTypeScriptFiles(path.join("core", "src", "devices"))) { const code = withoutComments(file.text).toLowerCase(); for (const forbidden of ["email", "password", "emailverified", "sendresetpassword"]) { expect(code, `${file.path} names ${forbidden}`).not.toContain(forbidden); } } }); it("keeps the device store out of the identity notification path entirely", async () => { const notifications = await readFile( path.join(repositoryRoot, "core", "src", "identity", "notifications.ts"), "utf8", ); expect(notifications).not.toContain("devices"); expect(notifications).not.toContain("Device"); }); }); describe("the browser shell reaches none of it", () => { it("imports neither Better Auth nor Core's mail from any browser source", async () => { for (const file of await readTypeScriptFiles(path.join("surfaces", "shell", "src"))) { expect(file.text, file.path).not.toContain("better-auth"); expect(file.text, file.path).not.toContain("@ekklesia/core/mail"); expect(file.text, file.path).not.toContain("nodemailer"); } }); it("declares no server identity or mail dependency in the shell package", async () => { const manifest = JSON.parse( await readFile(path.join(repositoryRoot, "surfaces", "shell", "package.json"), "utf8"), ) as Record | undefined>; const declared = Object.keys({ ...(manifest.dependencies ?? {}), ...(manifest.devDependencies ?? {}), }); expect(declared).not.toContain("better-auth"); expect(declared).not.toContain("nodemailer"); expect(declared).not.toContain("@ekklesia/core"); }); it("never puts a reset token in browser storage", async () => { for (const file of await readTypeScriptFiles(path.join("surfaces", "shell", "src"))) { const code = withoutComments(file.text); // A reset token is a bearer credential for one account; the shell holds it in React state for // the life of one form and nowhere else. expect(code, file.path).not.toContain("localStorage"); expect(code, file.path).not.toContain("sessionStorage"); expect(code, file.path).not.toContain("document.cookie"); } }); }); describe("public signup stays gone", () => { it("offers no registration path from any browser source", async () => { for (const file of await readTypeScriptFiles(path.join("surfaces", "shell", "src"))) { const code = withoutComments(file.text); // Email verification is not a licence to self-register (ADR 0038). expect(code, file.path).not.toContain("/sign-up"); expect(code, file.path).not.toContain("signUp"); } }); });