import { describe, expect, it } from "vitest"; import { buildAuditHeaders, runWithAuditActor } from "./audit-context"; const reader = (h: Record) => ({ get: (name: string) => h[name.toLowerCase()] ?? null, }); describe("buildAuditHeaders", () => { it("forwards the dashboard user's PB token from Authorization", () => { const out = buildAuditHeaders(reader({ authorization: "pb-user-token" }), undefined, "agent-key"); expect(out).toMatchObject({ "X-Audit-Source": "web", "X-Audit-Auth": "pb-user-token" }); }); it("uses the fetch-wrapper header when Authorization is absent", () => { const out = buildAuditHeaders(reader({ "x-wfdash-auth": "tok" }), undefined, "agent-key"); expect(out["X-Audit-Auth"]).toBe("tok"); }); it("never forwards the agent API key as a user token", () => { const out = buildAuditHeaders(reader({ authorization: "Bearer agent-key" }), undefined, "agent-key"); expect(out["X-Audit-Source"]).toBe("agent"); expect(out["X-Audit-Auth"]).toBeUndefined(); }); it("prefers the wrapper token over the agent key for agent-authed browser calls", () => { const out = buildAuditHeaders( reader({ authorization: "Bearer agent-key", "x-wfdash-auth": "tok" }), undefined, "agent-key", ); expect(out).toMatchObject({ "X-Audit-Source": "agent", "X-Audit-Auth": "tok" }); }); it("carries an explicit actor, URI-encoding non-ASCII names", () => { const out = buildAuditHeaders(null, { id: "u1", name: "Zoƫ Naidoo", source: "mcp" }, undefined); expect(out).toMatchObject({ "X-Audit-Source": "mcp", "X-Audit-Actor-Id": "u1", "X-Audit-Actor-Name": "Zo%C3%AB%20Naidoo", }); }); it("reads the dev-identity cookie as an email hint but never invents one", () => { expect( buildAuditHeaders(reader({ cookie: "a=1; wfdash_dev_email=sam%40wf.co.za" }), undefined, undefined)[ "X-Audit-Actor-Email" ], ).toBe("sam%40wf.co.za"); expect(buildAuditHeaders(reader({}), undefined, undefined)["X-Audit-Actor-Email"]).toBeUndefined(); }); it("omits the request user's token and email hint when the actor opts out (ignoreRequestUser)", () => { const incoming = reader({ authorization: "Bearer pb-user-token", "x-wfdash-auth": "tok", cookie: "wfdash_dev_email=sam%40wf.co.za", }); const out = buildAuditHeaders( incoming, { name: "AI quote assistant (run by Sam)", source: "agent", ignoreRequestUser: true }, "agent-key", ); expect(out["X-Audit-Auth"]).toBeUndefined(); expect(out["X-Audit-Actor-Email"]).toBeUndefined(); expect(out).toMatchObject({ "X-Audit-Source": "agent", "X-Audit-Actor-Name": encodeURIComponent("AI quote assistant (run by Sam)"), }); }); it("still forwards the request user's token when the actor does not opt out", () => { const out = buildAuditHeaders( reader({ authorization: "Bearer pb-user-token" }), { name: "Someone", source: "mcp" }, "agent-key", ); expect(out["X-Audit-Auth"]).toBe("pb-user-token"); }); it("falls back to source=server outside a request", () => { expect(buildAuditHeaders(null, undefined, undefined)).toEqual({ "X-Audit-Source": "server" }); }); }); describe("runWithAuditActor", () => { it("returns the callback's value", async () => { await expect(runWithAuditActor({ source: "mcp" }, async () => 42)).resolves.toBe(42); }); });