policy.test.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { describe, expect } from "bun:test"
  2. import { Effect, Layer } from "effect"
  3. import { Location } from "@opencode-ai/core/location"
  4. import { Policy } from "@opencode-ai/core/policy"
  5. import { AbsolutePath } from "@opencode-ai/core/schema"
  6. import { location } from "./fixture/location"
  7. import { testEffect } from "./lib/effect"
  8. const it = testEffect(
  9. Policy.locationLayer.pipe(
  10. Layer.provide(
  11. Layer.succeed(Location.Service, Location.Service.of(location({ directory: AbsolutePath.make("test") }))),
  12. ),
  13. ),
  14. )
  15. describe("Policy", () => {
  16. it.effect("returns the caller's fallback when no statement matches", () =>
  17. Effect.gen(function* () {
  18. const policy = yield* Policy.Service
  19. expect(yield* policy.evaluate("provider.use", "anthropic", "allow")).toBe("allow")
  20. expect(yield* policy.evaluate("provider.use", "anthropic", "deny")).toBe("deny")
  21. }),
  22. )
  23. it.effect("evaluates wildcard provider rules in written order", () =>
  24. Effect.gen(function* () {
  25. const policy = yield* Policy.Service
  26. yield* policy.load([
  27. new Policy.Info({
  28. effect: "deny",
  29. action: "provider.*",
  30. resource: "*",
  31. }),
  32. new Policy.Info({
  33. effect: "allow",
  34. action: "provider.use",
  35. resource: "anthropic",
  36. }),
  37. ])
  38. expect(yield* policy.evaluate("provider.use", "anthropic", "allow")).toBe("allow")
  39. expect(yield* policy.evaluate("provider.use", "openai", "allow")).toBe("deny")
  40. }),
  41. )
  42. it.effect("matches action and resource independently", () =>
  43. Effect.gen(function* () {
  44. const policy = yield* Policy.Service
  45. yield* policy.load([
  46. new Policy.Info({
  47. effect: "deny",
  48. action: "provider.*",
  49. resource: "company-*",
  50. }),
  51. ])
  52. expect(yield* policy.evaluate("provider.use", "company-stable", "allow")).toBe("deny")
  53. expect(yield* policy.evaluate("plugin.load", "company-stable", "allow")).toBe("allow")
  54. }),
  55. )
  56. it.effect("uses the last matching loaded statement", () =>
  57. Effect.gen(function* () {
  58. const policy = yield* Policy.Service
  59. yield* policy.load([
  60. new Policy.Info({
  61. effect: "allow",
  62. action: "provider.use",
  63. resource: "openai",
  64. }),
  65. new Policy.Info({
  66. effect: "deny",
  67. action: "provider.use",
  68. resource: "openai",
  69. }),
  70. ])
  71. expect(yield* policy.evaluate("provider.use", "openai", "allow")).toBe("deny")
  72. }),
  73. )
  74. })