63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
|
|
import { describe, expect, it } from "vitest";
|
||
|
|
|
||
|
|
import { buildAuditHeaders, runWithAuditActor } from "./audit-context";
|
||
|
|
|
||
|
|
const reader = (h: Record<string, string>) => ({
|
||
|
|
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("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);
|
||
|
|
});
|
||
|
|
});
|