diff --git a/.changeset/ack-id-controller-claim-did-uri.md b/.changeset/ack-id-controller-claim-did-uri.md new file mode 100644 index 00000000..af01212e --- /dev/null +++ b/.changeset/ack-id-controller-claim-did-uri.md @@ -0,0 +1,5 @@ +--- +"@agentcommercekit/ack-id": patch +--- + +Require `controllerClaimSchema` `id` and `controller` fields to be DID URIs in both Valibot and Zod, rejecting empty strings and other non-DID values at the schema boundary. diff --git a/packages/ack-id/src/schemas/schemas.test.ts b/packages/ack-id/src/schemas/schemas.test.ts new file mode 100644 index 00000000..ca49bfe3 --- /dev/null +++ b/packages/ack-id/src/schemas/schemas.test.ts @@ -0,0 +1,44 @@ +import * as v from "valibot" +import { describe, expect, it } from "vitest" + +import { controllerClaimSchema as valibotControllerClaimSchema } from "./valibot" +import { controllerClaimSchema as zodControllerClaimSchema } from "./zod" + +const validClaim = { + id: "did:web:agent.example.com", + controller: "did:web:controller.example.com", +} + +describe("controllerClaimSchema", () => { + it("accepts DID URIs for id and controller", () => { + expect(v.safeParse(valibotControllerClaimSchema, validClaim).success).toBe( + true, + ) + expect(zodControllerClaimSchema.safeParse(validClaim).success).toBe(true) + }) + + it("rejects empty id and controller strings", () => { + for (const input of [ + { ...validClaim, id: "" }, + { ...validClaim, controller: "" }, + { id: "", controller: "" }, + ]) { + expect(v.safeParse(valibotControllerClaimSchema, input).success).toBe( + false, + ) + expect(zodControllerClaimSchema.safeParse(input).success).toBe(false) + } + }) + + it("rejects non-DID id and controller values", () => { + for (const input of [ + { ...validClaim, id: "agent.example.com" }, + { ...validClaim, controller: "not-a-did" }, + ]) { + expect(v.safeParse(valibotControllerClaimSchema, input).success).toBe( + false, + ) + expect(zodControllerClaimSchema.safeParse(input).success).toBe(false) + } + }) +}) diff --git a/packages/ack-id/src/schemas/valibot.ts b/packages/ack-id/src/schemas/valibot.ts index 2f579840..11e11531 100644 --- a/packages/ack-id/src/schemas/valibot.ts +++ b/packages/ack-id/src/schemas/valibot.ts @@ -1,6 +1,7 @@ +import { didUriSchema } from "@agentcommercekit/did/schemas/valibot" import * as v from "valibot" export const controllerClaimSchema = v.object({ - id: v.string(), - controller: v.string(), + id: didUriSchema, + controller: didUriSchema, }) diff --git a/packages/ack-id/src/schemas/zod.ts b/packages/ack-id/src/schemas/zod.ts index 30751a5b..20007819 100644 --- a/packages/ack-id/src/schemas/zod.ts +++ b/packages/ack-id/src/schemas/zod.ts @@ -1,6 +1,7 @@ +import { didUriSchema } from "@agentcommercekit/did/schemas/zod" import * as z from "zod" export const controllerClaimSchema = z.object({ - id: z.string(), - controller: z.string(), + id: didUriSchema, + controller: didUriSchema, })