import { describe, it, expect, beforeAll } from "vitest"; beforeAll(() => { process.env.API_KEY_ENCRYPTION_SECRET = "unit-test-secret-0123456789abcdef0123456789abcdef"; }); describe("provider key encryption", () => { it("round-trips and binds ciphertext to the user/provider context", async () => { const { encryptSecret, decryptSecret, fingerprintSecret, keyHint, redactSecrets } = await import("@/lib/crypto/keys"); const ctx = { userId: "u1", provider: "openai" }; const env = encryptSecret("sk-proj-abcdefghijklmnopqrstuvwxyz0123456789ABCD", ctx); expect(env.startsWith("v1.")).toBe(true); expect(env.split(".")).toHaveLength(4); expect(decryptSecret(env, ctx)).toBe("sk-proj-abcdefghijklmnopqrstuvwxyz0123456789ABCD"); // different user → AAD mismatch → auth tag failure expect(() => decryptSecret(env, { userId: "u2", provider: "openai" })).toThrow(); expect(() => decryptSecret(env, { userId: "u1", provider: "anthropic" })).toThrow(); // never the plaintext expect(env).not.toContain("sk-proj"); // random IV → different envelopes for the same key expect(encryptSecret("same", ctx)).not.toBe(encryptSecret("same", ctx)); expect(fingerprintSecret("a")).toBe(fingerprintSecret("a")); expect(fingerprintSecret("a")).not.toBe(fingerprintSecret("b")); expect(keyHint("sk-ant-api03-verylongkeyvaluethatendswith9A2K")).toBe("sk-ant-••••••••9A2K"); expect(keyHint("xai-abcdefgh1234")).toBe("xai-••••••••1234"); expect(redactSecrets("Bearer sk-proj-abcdefghijklmnopqrstuvwxyz0123 and re_7KMNpXFh_JqMY4Gf4vxBYTVkiLhxB7WkA")).not.toMatch(/sk-proj-abc|re_7KMN/); }); });