import { describe, expect, it } from "vitest"; import { CapabilityDeniedError, createCapabilityGate, evaluateCapabilityGate, } from "./gate"; const fullConfig = { manifestPermissions: [ "files.read", "files.write", "storage.app", "notifications.write", ], grantedPermissions: [ "files.read", "files.write", "storage.app", "notifications.write", ], } as const; describe("evaluateCapabilityGate", () => { it("allows a declared, granted, within-ceiling operation", () => { const decision = evaluateCapabilityGate("files.create", { ...fullConfig, effectCeiling: "write", }); expect(decision.allowed).toBe(true); }); it("rejects unknown operations", () => { const decision = evaluateCapabilityGate("files.obliterate", { ...fullConfig, effectCeiling: "destructive", }); expect(decision).toMatchObject({ allowed: false, code: "unknown_operation" }); }); it("rejects operations whose permission is not declared in the manifest", () => { const decision = evaluateCapabilityGate("members.list", { ...fullConfig, effectCeiling: "read", }); expect(decision).toMatchObject({ allowed: false, code: "permission_not_declared", }); }); it("rejects operations declared but not granted to the install", () => { const decision = evaluateCapabilityGate("notifications.create", { manifestPermissions: fullConfig.manifestPermissions, grantedPermissions: ["files.read"], effectCeiling: "write", }); expect(decision).toMatchObject({ allowed: false, code: "permission_not_granted", }); }); describe("effect ceilings (the ยง10.3 invariant)", () => { it("a read tool cannot call write capabilities", () => { const decision = evaluateCapabilityGate("files.create", { ...fullConfig, effectCeiling: "read", }); expect(decision).toMatchObject({ allowed: false, code: "effect_ceiling_exceeded", }); }); it("a write tool cannot call destructive capabilities", () => { const decision = evaluateCapabilityGate("files.trash", { ...fullConfig, effectCeiling: "write", }); expect(decision).toMatchObject({ allowed: false, code: "effect_ceiling_exceeded", }); }); it("a destructive tool can call destructive capabilities", () => { const decision = evaluateCapabilityGate("files.trash", { ...fullConfig, effectCeiling: "destructive", }); expect(decision.allowed).toBe(true); }); it("an external tool is ceilinged at write for workspace mutations", () => { expect( evaluateCapabilityGate("files.create", { ...fullConfig, effectCeiling: "external", }).allowed, ).toBe(true); expect( evaluateCapabilityGate("files.trash", { ...fullConfig, effectCeiling: "external", }), ).toMatchObject({ allowed: false, code: "effect_ceiling_exceeded" }); }); it("render contexts (no ceiling supplied) are read-only", () => { const decision = evaluateCapabilityGate("files.create", fullConfig); expect(decision).toMatchObject({ allowed: false, code: "effect_ceiling_exceeded", }); expect(evaluateCapabilityGate("files.list", fullConfig).allowed).toBe(true); }); }); it("permissionless operations pass without grants but respect ceilings", () => { const config = { manifestPermissions: [], grantedPermissions: [] } as const; expect(evaluateCapabilityGate("workspace.get", config).allowed).toBe(true); expect(evaluateCapabilityGate("pickers.file", config).allowed).toBe(true); expect(evaluateCapabilityGate("navigation.openFile", config).allowed).toBe(true); }); }); describe("createCapabilityGate", () => { it("assert throws CapabilityDeniedError with the denial code", () => { const gate = createCapabilityGate({ ...fullConfig, effectCeiling: "read" }); expect(gate.assert("files.list")).toBe("files.list"); expect(() => gate.assert("files.create")).toThrowError(CapabilityDeniedError); try { gate.assert("files.create"); } catch (error) { expect((error as CapabilityDeniedError).code).toBe("effect_ceiling_exceeded"); } }); });