import { mkdirSync, mkdtempSync, realpathSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { assertMandatoryExtensionsLoaded, extensionPathMatches, normalizeMandatoryExtensionPaths, } from "../src/mandatory-extensions.js"; function fixturePath(name = "permission-system.ts"): string { const dir = mkdtempSync(join(tmpdir(), "pi-subagents-mandatory-")); const path = join(dir, name); writeFileSync(path, "export default () => {};\n"); return path; } describe("mandatory extension paths", () => { it("requires absolute existing extension entries and canonicalizes duplicates", () => { const path = fixturePath(); expect(normalizeMandatoryExtensionPaths([path, path])).toEqual([ realpathSync.native(path), ]); expect(() => normalizeMandatoryExtensionPaths(["relative.ts"])) .toThrow("must be absolute"); expect(() => normalizeMandatoryExtensionPaths([join(tmpdir(), "missing-extension.ts")])) .toThrow("is unavailable"); }); it("accepts extension directories", () => { const dir = mkdtempSync(join(tmpdir(), "pi-subagents-mandatory-dir-")); const extensionDir = join(dir, "permission-system"); mkdirSync(extensionDir); expect(normalizeMandatoryExtensionPaths([extensionDir])).toEqual([ realpathSync.native(extensionDir), ]); }); it("matches the exact canonical entry rather than a same-named impostor", () => { const trusted = fixturePath(); const impostor = fixturePath(); const [canonical] = normalizeMandatoryExtensionPaths([trusted]); expect(extensionPathMatches(trusted, canonical)).toBe(true); expect(extensionPathMatches(impostor, canonical)).toBe(false); }); it("fails closed when the exact mandatory entry did not survive reload", () => { const trusted = fixturePath(); const impostor = fixturePath(); const mandatory = normalizeMandatoryExtensionPaths([trusted]); expect(() => assertMandatoryExtensionsLoaded([impostor], mandatory)) .toThrow(`Mandatory extension failed to load: ${mandatory[0]}`); expect(() => assertMandatoryExtensionsLoaded([trusted], mandatory)).not.toThrow(); }); });