1import { describe, expect, it } from "@effect/vitest";
2import * as Schema from "effect/Schema";
3
4import {
5 AcpRegistryManagedBinaryUninstallInput,
6 AcpRegistryManagedBinaryUninstallResult,
7 officialAcpRegistryIconUrlForAgentId,
8 resolveOfficialAcpRegistryIconUrl,
9} from "./acpRegistry.ts";
10
11const decodeUninstallInput = Schema.decodeUnknownSync(AcpRegistryManagedBinaryUninstallInput);
12const decodeUninstallResult = Schema.decodeUnknownSync(AcpRegistryManagedBinaryUninstallResult);
13
14describe("ACP Registry contracts", () => {
15 it("accepts only official Registry icon URLs and safe agent IDs", () => {
16 expect(officialAcpRegistryIconUrlForAgentId("antigravity-acp")).toBe(
17 "https://cdn.agentclientprotocol.com/registry/v1/latest/antigravity-acp.svg",
18 );
19 expect(officialAcpRegistryIconUrlForAgentId("../antigravity-acp")).toBeNull();
20 expect(
21 resolveOfficialAcpRegistryIconUrl(
22 "https://cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg",
23 ),
24 ).toBe("https://cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg");
25 expect(
26 resolveOfficialAcpRegistryIconUrl(
27 "https://cdn.agentclientprotocol.com.evil/registry/v1/latest/pi-acp.svg",
28 ),
29 ).toBeNull();
30 expect(
31 resolveOfficialAcpRegistryIconUrl(
32 "https://user@cdn.agentclientprotocol.com/registry/v1/latest/pi-acp.svg",
33 ),
34 ).toBeNull();
35 });
36
37 it("decodes managed binary uninstall payloads and rejects unsafe agent IDs", () => {
38 expect(decodeUninstallInput({ agentId: " example-agent " })).toEqual({
39 agentId: "example-agent",
40 });
41 expect(decodeUninstallResult({ agentId: "example-agent", removed: false })).toEqual({
42 agentId: "example-agent",
43 removed: false,
44 });
45 expect(() => decodeUninstallInput({ agentId: "../example-agent" })).toThrow();
46 });
47});