fix(api): wrap audit log writes inside their parent transactions
Prevents mutations from committing without an audit trail if the auditLog.create call fails after the main write already succeeded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -221,13 +221,14 @@ describe("project router", () => {
|
||||
describe("create", () => {
|
||||
it("creates a project and returns its id", async () => {
|
||||
const created = { ...sampleProject, id: "project_new" };
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
project: {
|
||||
findUnique: vi.fn().mockResolvedValue(null), // no shortCode conflict
|
||||
create: vi.fn().mockResolvedValue(created),
|
||||
},
|
||||
auditLog: { create: vi.fn().mockResolvedValue({}) },
|
||||
webhook: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
$transaction: vi.fn(async (fn: (tx: unknown) => unknown) => fn(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -253,13 +254,14 @@ describe("project router", () => {
|
||||
vi.mocked(dispatchWebhooks).mockRejectedValueOnce(new Error("webhook unavailable"));
|
||||
|
||||
const created = { ...sampleProject, id: "project_safe_create" };
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
project: {
|
||||
findUnique: vi.fn().mockResolvedValue(null),
|
||||
create: vi.fn().mockResolvedValue(created),
|
||||
},
|
||||
auditLog: { create: vi.fn().mockResolvedValue({}) },
|
||||
webhook: { findMany: vi.fn().mockResolvedValue([]) },
|
||||
$transaction: vi.fn(async (fn: (tx: unknown) => unknown) => fn(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -451,12 +453,13 @@ describe("project router", () => {
|
||||
describe("update", () => {
|
||||
it("updates project fields", async () => {
|
||||
const updated = { ...sampleProject, name: "Updated Name" };
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
project: {
|
||||
findUnique: vi.fn().mockResolvedValue(sampleProject),
|
||||
update: vi.fn().mockResolvedValue(updated),
|
||||
},
|
||||
auditLog: { create: vi.fn().mockResolvedValue({}) },
|
||||
$transaction: vi.fn(async (fn: (tx: unknown) => unknown) => fn(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -558,14 +561,12 @@ describe("project router", () => {
|
||||
|
||||
describe("batchUpdateStatus", () => {
|
||||
it("updates multiple projects and returns count", async () => {
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
project: {
|
||||
update: vi.fn().mockResolvedValue(sampleProject),
|
||||
},
|
||||
auditLog: { create: vi.fn().mockResolvedValue({}) },
|
||||
$transaction: vi.fn((calls: unknown[]) =>
|
||||
Promise.all((calls as Promise<unknown>[]).map(() => sampleProject)),
|
||||
),
|
||||
$transaction: vi.fn(async (fn: (tx: unknown) => unknown) => fn(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -575,7 +576,7 @@ describe("project router", () => {
|
||||
});
|
||||
|
||||
expect(result.count).toBe(3);
|
||||
expect(db.auditLog.create).toHaveBeenCalled();
|
||||
expect((db.auditLog as Record<string, ReturnType<typeof vi.fn>>).create).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user