import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { sanitizedEnv } from "../../src/runtime/env"; describe("sanitizedEnv", () => { const originalEnv = process.env; beforeEach(() => { // Work with a clean clone so mutations don't bleed between tests process.env = { ...originalEnv }; }); afterEach(() => { process.env = originalEnv; }); it("(a) removes DISCORD_BOT_TOKEN from the child environment", () => { process.env["DISCORD_BOT_TOKEN"] = "secret-bot-token"; process.env["DISCORD_CLIENT_SECRET"] = "secret-client"; process.env["DISCORD_PUBLIC_KEY"] = "public-key-value"; const result = sanitizedEnv(); expect(result["DISCORD_BOT_TOKEN"]).toBeUndefined(); expect(result["DISCORD_CLIENT_SECRET"]).toBeUndefined(); expect(result["DISCORD_PUBLIC_KEY"]).toBeUndefined(); }); it("(b) removes keys matching pattern blocklist: SECRET_*, TOKEN_*, API_KEY*, DISCLAW_SECRET_*", () => { process.env["SECRET_FOO"] = "foo-value"; process.env["TOKEN_BAR"] = "bar-value"; process.env["API_KEY_TEST"] = "test-key"; process.env["API_KEY"] = "bare-key"; process.env["DISCLAW_SECRET_X"] = "x-value"; const result = sanitizedEnv(); expect(result["SECRET_FOO"]).toBeUndefined(); expect(result["TOKEN_BAR"]).toBeUndefined(); expect(result["API_KEY_TEST"]).toBeUndefined(); expect(result["API_KEY"]).toBeUndefined(); expect(result["DISCLAW_SECRET_X"]).toBeUndefined(); }); it("(c) preserves PATH, HOME, USERPROFILE and other safe env vars", () => { process.env["PATH"] = "/usr/bin:/bin"; process.env["HOME"] = "/home/user"; process.env["USERPROFILE"] = "C:\\Users\\user"; process.env["SOME_SAFE_VAR"] = "safe-value"; const result = sanitizedEnv(); expect(result["PATH"]).toBe("/usr/bin:/bin"); expect(result["HOME"]).toBe("/home/user"); expect(result["USERPROFILE"]).toBe("C:\\Users\\user"); expect(result["SOME_SAFE_VAR"]).toBe("safe-value"); }); it("(c) sets CI=true and DISCLAW_AGENT=1 as mandatory markers", () => { const result = sanitizedEnv(); expect(result["CI"]).toBe("true"); expect(result["DISCLAW_AGENT"]).toBe("1"); }); it("(d) extra parameter overrides defaults and adds new keys", () => { process.env["SOME_KEY"] = "original"; const result = sanitizedEnv({ DISCLAW_AGENT_NAME: "my-agent", CI: "false", // override the mandatory default EXTRA_CUSTOM: "custom-value", }); expect(result["DISCLAW_AGENT_NAME"]).toBe("my-agent"); expect(result["CI"]).toBe("false"); expect(result["EXTRA_CUSTOM"]).toBe("custom-value"); // Keys not in extra are still present expect(result["SOME_KEY"]).toBe("original"); }); it("(e) additionalBlocklist removes the specified keys after extras are merged", () => { process.env["MY_INTERNAL_SECRET"] = "internal"; process.env["ANOTHER_KEY"] = "another"; const result = sanitizedEnv( { DISCLAW_AGENT_NAME: "test-agent" }, ["MY_INTERNAL_SECRET", "ANOTHER_KEY"] ); expect(result["MY_INTERNAL_SECRET"]).toBeUndefined(); expect(result["ANOTHER_KEY"]).toBeUndefined(); // Extras and standard vars should still be present expect(result["DISCLAW_AGENT_NAME"]).toBe("test-agent"); expect(result["CI"]).toBe("true"); }); it("does not mutate process.env", () => { process.env["DISCORD_BOT_TOKEN"] = "sensitive"; const tokenBefore = process.env["DISCORD_BOT_TOKEN"]; sanitizedEnv({ DISCLAW_AGENT_NAME: "agent" }, ["DISCORD_BOT_TOKEN"]); // process.env must be unchanged expect(process.env["DISCORD_BOT_TOKEN"]).toBe(tokenBefore); }); });