feat(confidence-engine): add authenticated investigation persistence

This commit is contained in:
2026-09-08 17:15:46 +01:00
parent b949eea831
commit 6dd447e56a
6 changed files with 193 additions and 3 deletions
@@ -0,0 +1,81 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mockGetAuthenticatedUser = vi.fn();
const mockCreateServerSupabaseClient = vi.fn();
vi.mock("@/lib/supabase/server.js", () => ({
getAuthenticatedUser: () => mockGetAuthenticatedUser(),
createServerSupabaseClient: () => mockCreateServerSupabaseClient(),
}));
function makeClient(result) {
const query = {
from: vi.fn(() => query),
upsert: vi.fn(() => query),
select: vi.fn(() => query),
eq: vi.fn(() => query),
maybeSingle: vi.fn(() => Promise.resolve(result)),
single: vi.fn(() => Promise.resolve(result)),
order: vi.fn(() => Promise.resolve(result)),
};
return { client: { schema: vi.fn(() => query) }, query };
}
describe("server investigation persistence", () => {
beforeEach(() => vi.clearAllMocks());
it("rejects unauthenticated persistence access", async () => {
mockGetAuthenticatedUser.mockResolvedValue(null);
const { saveInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
await expect(saveInvestigation({ id: "investigation-1" })).resolves.toBeNull();
expect(mockCreateServerSupabaseClient).not.toHaveBeenCalled();
});
it("saves an unchanged snapshot with user identity derived on the server", async () => {
const snapshot = { id: "investigation-1", scenario: "A situation", user_id: "untrusted" };
const { client, query } = makeClient({ data: { snapshot }, error: null });
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
mockCreateServerSupabaseClient.mockReturnValue(client);
const { saveInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
await expect(saveInvestigation(snapshot)).resolves.toBe(snapshot);
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
expect(query.from).toHaveBeenCalledWith("investigations");
expect(query.upsert).toHaveBeenCalledWith(
{ id: "investigation-1", user_id: "trusted-user", snapshot },
{ onConflict: "id" },
);
});
it("loads the RLS-scoped stored snapshot", async () => {
const snapshot = { id: "investigation-1", findings: [] };
const { client, query } = makeClient({ data: { snapshot }, error: null });
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
mockCreateServerSupabaseClient.mockReturnValue(client);
const { loadInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
await expect(loadInvestigation("investigation-1")).resolves.toBe(snapshot);
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
expect(query.eq).toHaveBeenCalledWith("id", "investigation-1");
});
it("lists only RLS-visible persistence records", async () => {
const { client, query } = makeClient({
data: [{ id: "investigation-1", created_at: "2026-09-08T00:00:00Z", updated_at: "2026-09-08T01:00:00Z" }],
error: null,
});
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
mockCreateServerSupabaseClient.mockReturnValue(client);
const { listInvestigations } = await import("@/lib/storage/server-investigation-persistence.js");
await expect(listInvestigations()).resolves.toEqual([{
id: "investigation-1",
createdAt: "2026-09-08T00:00:00Z",
updatedAt: "2026-09-08T01:00:00Z",
}]);
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
expect(query.select).toHaveBeenCalledWith("id, created_at, updated_at");
expect(query.order).toHaveBeenCalledWith("updated_at", { ascending: false });
});
});