diff --git a/packages/core/src/permission.ts b/packages/core/src/permission.ts index 29a8e3720a7a..31a93781fb6a 100644 --- a/packages/core/src/permission.ts +++ b/packages/core/src/permission.ts @@ -170,6 +170,12 @@ const layer = Layer.effect( return { effect, rules: all } }) + // Metadata is JSON-encoded; drop undefined values tools pass for absent optional inputs. + function metadata(value: AssertInput["metadata"]): Request["metadata"] { + if (!value) return value + return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined)) + } + function request(input: AssertInput): Request { return { id: input.id ?? ID.create(), @@ -177,7 +183,7 @@ const layer = Layer.effect( action: input.action, resources: input.resources, save: input.save, - metadata: input.metadata, + metadata: metadata(input.metadata), source: input.source, } } diff --git a/packages/core/test/permission.test.ts b/packages/core/test/permission.test.ts index 669fb4d9691e..a94b41dcf6ef 100644 --- a/packages/core/test/permission.test.ts +++ b/packages/core/test/permission.test.ts @@ -266,6 +266,17 @@ describe("PermissionV2", () => { }), ) + it.effect("omits undefined metadata values from pending requests", () => + Effect.gen(function* () { + yield* setup() + const service = yield* PermissionV2.Service + yield* service.ask(assertion({ metadata: { root: ".", path: undefined, limit: undefined } })) + const request = yield* service.get(PermissionV2.ID.create("per_test")) + expect(request?.metadata).toEqual({ root: "." }) + expect(Object.keys(request?.metadata ?? {})).toEqual(["root"]) + }), + ) + it.effect("defects when an asked permission is declined", () => Effect.gen(function* () { yield* setup()