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:
@@ -434,9 +434,10 @@ describe("estimate router", () => {
|
||||
const estimateCreate = vi.fn().mockResolvedValue(created);
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { create: estimateCreate },
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -474,10 +475,11 @@ describe("estimate router", () => {
|
||||
});
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { create: estimateCreate },
|
||||
project: { findUnique: projectFindUnique },
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -699,7 +701,7 @@ describe("estimate router", () => {
|
||||
const updateEstimate = vi.fn().mockResolvedValue({});
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: {
|
||||
findUnique,
|
||||
update: updateEstimate,
|
||||
@@ -709,13 +711,8 @@ describe("estimate router", () => {
|
||||
update: updateVersion,
|
||||
},
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) =>
|
||||
callback({
|
||||
estimateVersion: { updateMany, update: updateVersion },
|
||||
estimate: { update: updateEstimate },
|
||||
}),
|
||||
),
|
||||
};
|
||||
db["$transaction"] = vi.fn(async (callback: (tx: unknown) => unknown) => callback(db));
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
const result = await caller.submitVersion({ estimateId: "est_1" });
|
||||
@@ -803,7 +800,7 @@ describe("estimate router", () => {
|
||||
const updateEstimate = vi.fn().mockResolvedValue({});
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: {
|
||||
findUnique,
|
||||
update: updateEstimate,
|
||||
@@ -813,13 +810,8 @@ describe("estimate router", () => {
|
||||
update: updateVersion,
|
||||
},
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) =>
|
||||
callback({
|
||||
estimateVersion: { updateMany, update: updateVersion },
|
||||
estimate: { update: updateEstimate },
|
||||
}),
|
||||
),
|
||||
};
|
||||
db["$transaction"] = vi.fn(async (callback: (tx: unknown) => unknown) => callback(db));
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
const result = await caller.approveVersion({ estimateId: "est_1" });
|
||||
@@ -903,7 +895,7 @@ describe("estimate router", () => {
|
||||
const updateEstimate = vi.fn().mockResolvedValue({});
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: {
|
||||
findUnique,
|
||||
update: updateEstimate,
|
||||
@@ -915,18 +907,8 @@ describe("estimate router", () => {
|
||||
resourceCostSnapshot: { createMany: createSnapshots },
|
||||
estimateMetric: { createMany: createMetrics },
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) =>
|
||||
callback({
|
||||
estimateVersion: { create: createVersion },
|
||||
estimateAssumption: { createMany: createAssumptions },
|
||||
scopeItem: { create: createScopeItem },
|
||||
estimateDemandLine: { createMany: createDemandLines },
|
||||
resourceCostSnapshot: { createMany: createSnapshots },
|
||||
estimateMetric: { createMany: createMetrics },
|
||||
estimate: { update: updateEstimate },
|
||||
}),
|
||||
),
|
||||
};
|
||||
db["$transaction"] = vi.fn(async (callback: (tx: unknown) => unknown) => callback(db));
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
const result = await caller.createRevision({ estimateId: "est_1" });
|
||||
@@ -1008,12 +990,13 @@ describe("estimate router", () => {
|
||||
const estimateCreate = vi.fn().mockResolvedValue(cloned);
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: {
|
||||
findUnique: estimateFindUnique,
|
||||
create: estimateCreate,
|
||||
},
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -1026,9 +1009,10 @@ describe("estimate router", () => {
|
||||
it("throws NOT_FOUND when source estimate does not exist", async () => {
|
||||
const findUnique = vi.fn().mockResolvedValue(null);
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { findUnique },
|
||||
auditLog: { create: vi.fn() },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -1130,10 +1114,11 @@ describe("estimate router", () => {
|
||||
const updateVersion = vi.fn().mockResolvedValue({});
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { findUnique: estimateFindUnique },
|
||||
estimateVersion: { update: updateVersion },
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -1279,10 +1264,11 @@ describe("estimate router", () => {
|
||||
const createExport = vi.fn().mockResolvedValue({ id: "exp_1" });
|
||||
const auditLogCreate = vi.fn().mockResolvedValue({});
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { findUnique: estimateFindUnique },
|
||||
estimateExport: { create: createExport },
|
||||
auditLog: { create: auditLogCreate },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
@@ -1300,10 +1286,11 @@ describe("estimate router", () => {
|
||||
it("throws NOT_FOUND when estimate does not exist", async () => {
|
||||
const findUnique = vi.fn().mockResolvedValue(null);
|
||||
|
||||
const db = {
|
||||
const db: Record<string, unknown> = {
|
||||
estimate: { findUnique },
|
||||
estimateExport: { create: vi.fn() },
|
||||
auditLog: { create: vi.fn() },
|
||||
$transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
|
||||
Reference in New Issue
Block a user