import { describe, expect, test } from "bun:test"; import type { Db, Dialect, Driver, ExecResult, Row, TxHandle } from "@wrnexus/db"; import { dbPermissionStore } from "../src/db.ts"; /** * A deterministic regression guard for C1/C2 (round-1 review): grant() used to * wrap its delete-then-insert in db.tx, and the sqlite driver runs a bare * BEGIN on one shared, unserialized connection - so an open transaction there * could sweep in and discard a concurrent bare write from another method. * Timing-based tests can't reliably prove the absence of that; this can, * because it needs no concurrency at all - it just asserts the store never * asks the driver to open a transaction in the first place. */ function makeFakeDb(): { db: Db; statements: string[]; transactionCalls: number } { const statements: string[] = []; const stats = { transactionCalls: 0 }; const driver: Driver = { dialect: "sqlite" as Dialect, async query(sql: string): Promise { statements.push(sql); return []; }, async exec(sql: string): Promise { statements.push(sql); return { changes: 0 }; }, async transaction(fn: (tx: TxHandle) => Promise): Promise { // The spy: this must never be called by a transaction-free store. stats.transactionCalls++; statements.push("BEGIN"); return fn(driver); }, close() {}, }; const db: Db = { driver, async all(sql: string): Promise { statements.push(sql); return []; }, async one(sql: string): Promise { statements.push(sql); return null; }, async exec(sql: string): Promise { statements.push(sql); return { changes: 0 }; }, async tx(fn: (tx: Db) => Promise): Promise { // Routed through the same driver.transaction spy a real Db would use. return driver.transaction(() => fn(db)); }, async createTable() {}, close() {}, }; return { db, statements, get transactionCalls() { return stats.transactionCalls; }, }; } describe("dbPermissionStore opens no transaction", () => { test("the store opens no transaction: a shared-connection rollback would discard concurrent writes from other methods", async () => { const fake = makeFakeDb(); const store = dbPermissionStore(fake.db); await store.assignmentsFor("u1"); await store.assignRole("u1", "editor"); await store.revokeRole("u1", "editor"); await store.grant("u1", "post:write", "allow"); await store.revokeGrant("u1", "post:write"); await store.listSubjects(); expect(fake.transactionCalls).toBe(0); for (const sql of fake.statements) { expect(sql).not.toContain("BEGIN"); } }); });