From e0692efba8b990760f55863c8ba1e0eec47b6715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 8 Aug 2026 21:14:23 +0200 Subject: [PATCH] fix(sharing): widen the grant db slice for the expired-row sweep The pre-create sweep in inviteGrant writes an audit row when it closes a lapsed grant, so the transaction slice it accepts now covers auditLog alongside accountGrant. Point the module and route test fakes at the same shape: they stub updateMany to close nothing, so the audit branch stays unreached in the unit fixtures. --- .../grants/__tests__/invite-access-level.test.ts | 7 ++++++- .../grants/__tests__/invite-scope-and-manage.test.ts | 7 ++++++- src/lib/sharing/__tests__/grants.test.ts | 12 ++++++++---- src/lib/sharing/grants.ts | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/app/api/account/grants/__tests__/invite-access-level.test.ts b/src/app/api/account/grants/__tests__/invite-access-level.test.ts index 2507d194e..3798cc52f 100644 --- a/src/app/api/account/grants/__tests__/invite-access-level.test.ts +++ b/src/app/api/account/grants/__tests__/invite-access-level.test.ts @@ -38,7 +38,12 @@ vi.mock("@/lib/api-handler", async () => { vi.mock("@/lib/db", () => ({ prisma: { user: { findFirst: vi.fn() }, - accountGrant: { create: vi.fn() }, + accountGrant: { + create: vi.fn(), + // inviteGrant sweeps expired live-pair rows before the create; nothing to + // close in these fixtures. + updateMany: vi.fn().mockResolvedValue({ count: 0 }), + }, }, })); diff --git a/src/app/api/account/grants/__tests__/invite-scope-and-manage.test.ts b/src/app/api/account/grants/__tests__/invite-scope-and-manage.test.ts index 1c290d0a5..265283687 100644 --- a/src/app/api/account/grants/__tests__/invite-scope-and-manage.test.ts +++ b/src/app/api/account/grants/__tests__/invite-scope-and-manage.test.ts @@ -43,7 +43,12 @@ vi.mock("@/lib/api-handler", async () => { vi.mock("@/lib/db", () => ({ prisma: { user: { findFirst: vi.fn() }, - accountGrant: { create: vi.fn() }, + accountGrant: { + create: vi.fn(), + // inviteGrant sweeps expired live-pair rows before the create. No such + // row exists in these unit fixtures, so it closes nothing. + updateMany: vi.fn().mockResolvedValue({ count: 0 }), + }, }, })); diff --git a/src/lib/sharing/__tests__/grants.test.ts b/src/lib/sharing/__tests__/grants.test.ts index d3aa064f1..7aac92b03 100644 --- a/src/lib/sharing/__tests__/grants.test.ts +++ b/src/lib/sharing/__tests__/grants.test.ts @@ -154,7 +154,7 @@ describe("grantAllows", () => { */ describe("inviteGrant", () => { function captureDb(): { - db: Pick; + db: Pick; writes: Array<{ access: string; grantorId: string; @@ -170,6 +170,9 @@ describe("inviteGrant", () => { }> = []; const db = { accountGrant: { + // No expired live-pair row in these fixtures, so the pre-create sweep + // closes nothing and the audit branch is never reached. + updateMany: async () => ({ count: 0 }), create: async (args: { data: { access: string; @@ -182,7 +185,7 @@ describe("inviteGrant", () => { return { id: "grant-1", ...args.data } as unknown as AccountGrant; }, }, - } as unknown as Pick; + } as unknown as Pick; return { db, writes }; } @@ -391,18 +394,19 @@ describe("grantCoversDomain", () => { describe("inviteGrant, on scope", () => { function captureScopeDb(): { - db: Pick; + db: Pick; writes: Array<{ scopeJson: unknown }>; } { const writes: Array<{ scopeJson: unknown }> = []; const db = { accountGrant: { + updateMany: async () => ({ count: 0 }), create: async (args: { data: { scopeJson: unknown } }) => { writes.push(args.data); return { id: "grant-1", ...args.data } as unknown as AccountGrant; }, }, - } as unknown as Pick; + } as unknown as Pick; return { db, writes }; } diff --git a/src/lib/sharing/grants.ts b/src/lib/sharing/grants.ts index 7ffa09461..30a51a9c2 100644 --- a/src/lib/sharing/grants.ts +++ b/src/lib/sharing/grants.ts @@ -133,7 +133,7 @@ export class GrantError extends Error { * The narrow client slice these functions need, so a caller can pass a * transaction handle. Same shape as `issue-token.ts`. */ -type GrantDb = Pick; +type GrantDb = Pick; // ── The state machine, pure ─────────────────────────────────────────────────