import assert from "node:assert/strict"; import { test } from "node:test"; import { loadModule, modulePin, pdsOf, runModule } from "./index.js"; const did = "did:plc:alice"; const C = "xyz.example.thing"; const uri = (rkey) => `at://${did}/${C}/${rkey}`; // A stub module: on start each entry makes the calls given for it (ids c0, c1, ...), then waits for them. const moduleOf = (calls) => ({ module: new Uint8Array(), calls: ["com.atproto.repo.createRecord", "com.atproto.repo.putRecord", "com.atproto.repo.deleteRecord", "com.atproto.repo.applyWrites"], ...calls }); const ledger = () => { const rows = new Map(); return { rows, get: async (id) => rows.get(id) ?? null, put: async (id, data) => void rows.set(id, data), delete: async (id) => rows.delete(id) }; }; const ctxWith = (store, steps) => ({ storage: store && { managed_records: store }, wasm: { run: async ({ entry, input }) => (input.event.type === "start" ? { calls: (steps[entry] ?? []).map((call, i) => ({ id: `c${i}`, ...call })) } : {}) }, }); // The run's call log in call order (c0, c1, ...), whatever order they finished in. const logOf = (ran) => ran.calls.toSorted((a, b) => a.id.localeCompare(b.id)); const pds = async (nsid, { input }) => { if (nsid === "com.atproto.repo.createRecord") return { uri: uri(input.rkey ?? "new"), cid: "c" }; if (nsid === "com.atproto.repo.applyWrites") return { results: input.writes.map((w) => (w.$type.endsWith("#create") ? { uri: uri(w.rkey), cid: "c" } : {})) }; return {}; }; const write = (nsid, rkey) => ({ nsid, input: { repo: did, collection: C, rkey, ...(nsid !== "com.atproto.repo.deleteRecord" && { record: {} }) } }); test("a module may update and delete what it created, and nothing else", async () => { const store = ledger(); const steps = { create: [write("com.atproto.repo.createRecord")], put: [write("com.atproto.repo.putRecord", "new"), write("com.atproto.repo.putRecord", "other")], del: [write("com.atproto.repo.deleteRecord", "new"), write("com.atproto.repo.deleteRecord", "other")], }; const ctx = ctxWith(store, steps); await runModule(ctx, moduleOf(), "create", {}, pds); assert.ok(store.rows.has(uri("new"))); const put = await runModule(ctx, moduleOf(), "put", {}, pds); assert.deepEqual(logOf(put).map((c) => c.ok), [true, false]); assert.match(logOf(put)[1].error, /putRecord refused: at:\/\/did:plc:alice\/xyz.example.thing\/other was not created by this module/); const del = await runModule(ctx, moduleOf(), "del", {}, pds); assert.deepEqual(logOf(del).map((c) => c.ok), [true, false]); assert.equal(store.rows.has(uri("new")), false); }); test("the ledger is per module: another module, or an entry with no owner, cannot update or delete", async () => { const store = ledger(); const steps = { create: [write("com.atproto.repo.createRecord")], del: [write("com.atproto.repo.deleteRecord", "new")], old: [write("com.atproto.repo.deleteRecord", "old")] }; const mine = moduleOf({ id: "at://did:plc:pub/com.fedfork.exec.wasm.module/m" }); const other = moduleOf({ id: "at://did:plc:evil/com.fedfork.exec.wasm.module/m" }); await runModule(ctxWith(store, steps), mine, "create", {}, pds); assert.equal(store.rows.get(uri("new")).module, mine.id); const denied = await runModule(ctxWith(store, steps), other, "del", {}, pds); assert.match(logOf(denied)[0].error, /was not created by this module/); store.rows.set(uri("old"), { createdAt: "2026-01-01T00:00:00.000Z" }); // written before owners were recorded assert.match(logOf(await runModule(ctxWith(store, steps), mine, "old", {}, pds))[0].error, /was not created by this module/); assert.equal(logOf(await runModule(ctxWith(store, steps), mine, "del", {}, pds))[0].ok, true); assert.ok(!store.rows.has(uri("new"))); // no id: the module's sha256; owner (a composition's) wins over both await runModule(ctxWith(store, steps), moduleOf({ module: Uint8Array.of(1) }), "create", {}, pds); assert.equal(store.rows.get(uri("new")).module, "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"); await runModule(ctxWith(store, steps), { ...mine, owner: "composition:x" }, "create", {}, pds); assert.equal(store.rows.get(uri("new")).module, "composition:x"); }); test("calls and anyRecords must be absent or lists of strings (a string would match substrings)", async () => { const ctx = ctxWith(ledger(), {}); for (const bad of [{ calls: "com.atproto.repo.createRecord" }, { calls: null }, { anyRecords: C }, { anyRecords: [1] }]) { await assert.rejects(runModule(ctx, moduleOf(bad), "x", {}, pds), /must be a list of strings/); } await runModule(ctx, moduleOf({ calls: undefined, anyRecords: [C] }), "x", {}, pds); }); test("pdsOf: https off the host's network only, unless allowPrivate", async () => { const docs = new Map(); const fetched = []; const ctx = { http: { fetch: async (url) => (fetched.push(url), Response.json(docs.get(url) ?? {}, { status: docs.has(url) ? 200 : 404 })) } }; const doc = (endpoint) => ({ service: [{ id: "#atproto_pds", serviceEndpoint: endpoint }] }); const plc = (endpoint) => (docs.set("https://plc.directory/did:plc:a", doc(endpoint)), pdsOf(ctx, "did:plc:a")); assert.equal(await plc("https://pds.example"), "https://pds.example"); for (const bad of ["http://pds.example", "https://127.0.0.1", "https://localhost:3000", "https://169.254.169.254/latest", "https://10.1.2.3", "https://172.20.0.1", "https://192.168.1.1", "https://100.64.0.1", "https://0.0.0.0", "https://[::1]", "https://[fd00::1]", "https://[fe80::1]", "https://[::ffff:127.0.0.1]", "https://2130706433", "file:///etc/passwd", "nope"]) await assert.rejects(plc(bad), /not https|private address|not a URL/, bad); fetched.length = 0; for (const did of ["did:web:localhost%3A8080", "did:web:127.0.0.1", "did:web:%5B%3A%3A1%5D"]) await assert.rejects(pdsOf(ctx, did), /private address|not a URL/, did); assert.deepEqual(fetched, [], "nothing private was fetched"); docs.set("https://plc.directory/did:plc:a", doc("http://127.0.0.1:2583")); assert.equal(await pdsOf(ctx, "did:plc:a", { allowPrivate: true }), "http://127.0.0.1:2583"); assert.equal(await pdsOf({ ...ctx, allowPrivate: true }, "did:plc:a"), "http://127.0.0.1:2583"); }); test("loadModule: the record's didkey and the at:// URI as id; refuses bad lists and odd replies", async () => { const URI = "at://did:plc:pub/com.fedfork.exec.wasm.module/m"; const cid = "bafkreie5737gdxlw5i64vzichcalba3z2v5n6icifvx5xytvske7mr3hpm"; let value; const ctx = { http: { fetch: async (url) => { if (url.startsWith("https://plc.directory/")) return Response.json({ service: [{ id: "#atproto_pds", serviceEndpoint: "https://pds.example" }] }); if (url.includes("getRecord")) return Response.json(value); return new Response(new Uint8Array([0, 97, 115, 109])); }, }, }; const record = (extra) => ({ value: { abi: "emdash-wasm-json-v1", module: { ref: { $link: cid } }, calls: ["a.b.c"], ...extra } }); value = record({ didkey: { services: ["https://xrpc.fedproxy.com"] } }); const mod = await loadModule(ctx, URI); assert.equal(mod.id, URI); assert.deepEqual(mod.didkey, { services: ["https://xrpc.fedproxy.com"] }); value = record({ calls: "a.b.c" }); await assert.rejects(loadModule(ctx, URI), /calls must be a list of strings/); for (value of [[1, 2], "x", null, {}]) await assert.rejects(loadModule(ctx, URI), /unsupported module ABI/); }); test("loadModule: /, / and the at:// URI load the same record; @pin is checked", async () => { const URI = "at://did:plc:pub/com.fedfork.exec.wasm.module/m"; const cid = "bafkreie5737gdxlw5i64vzichcalba3z2v5n6icifvx5xytvske7mr3hpm"; let claimed = ["at://pub.example"]; const ctx = { http: { fetch: async (url) => { if (url.includes("resolveHandle")) return new URL(url).searchParams.get("handle") === "pub.example" ? Response.json({ did: "did:plc:pub" }) : new Response("{}", { status: 400 }); if (url.startsWith("https://plc.directory/")) return Response.json({ alsoKnownAs: claimed, service: [{ id: "#atproto_pds", serviceEndpoint: "https://pds.example" }] }); if (url.includes("getRecord")) return Response.json({ cid: "bafyrecord", value: { abi: "emdash-wasm-json-v1", module: { ref: { $link: cid } }, calls: ["a.b.c"] } }); return new Response(new Uint8Array([0, 97, 115, 109])); }, }, }; const [byHandle, byDid, byUri] = await Promise.all(["pub.example/m", "did:plc:pub/m", URI].map((ref) => loadModule(ctx, ref))); assert.deepEqual([byHandle.id, byDid.id], [URI, URI], "the id is the at:// URI, however it was named"); assert.deepEqual(byHandle, byUri); assert.deepEqual(byDid, byUri); const pin = await modulePin(byUri); for (const ok of ["pub.example/m@bafyrecord", `pub.example/m@${pin}`, `did:plc:pub/m@${pin.slice(0, 32)}`]) assert.equal((await loadModule(ctx, ok)).id, URI, ok); await assert.rejects(loadModule(ctx, `pub.example/m@${pin.slice(0, 31)}`), /at least 32 hex/); await assert.rejects(loadModule(ctx, `pub.example/m@${"0".repeat(32)}`), /pub.example\/m@0+: pinned to 0+, but it is pin/); await assert.rejects(loadModule(ctx, "nobody.example/m"), /nobody.example did not resolve/); claimed = ["at://someone.else"]; await assert.rejects(loadModule(ctx, "pub.example/m"), /does not claim it/); }); test("anyRecords opens a collection; without a ledger nothing is managed", async () => { const steps = { del: [write("com.atproto.repo.deleteRecord", "x")] }; const seen = []; const call = async (nsid, request) => seen.push(nsid) && {}; assert.equal(logOf(await runModule(ctxWith(undefined, steps), moduleOf({ anyRecords: [C] }), "del", {}, call))[0].ok, true); const refused = await runModule(ctxWith(undefined, steps), moduleOf(), "del", {}, call); assert.equal(logOf(refused)[0].ok, false); assert.equal(seen.length, 1, "a refused call never reaches the PDS"); const bare = await runModule(ctxWith(ledger(), { del: [{ nsid: "com.atproto.repo.deleteRecord" }] }), moduleOf(), "del", {}, call); assert.match(logOf(bare)[0].error, /refused/, "a write with no input is refused, not thrown"); }); test("applyWrites is checked per write and its creates are remembered", async () => { const store = ledger(); const op = (kind, rkey) => ({ $type: `com.atproto.repo.applyWrites#${kind}`, collection: C, rkey, ...(kind !== "delete" && { value: {} }) }); const apply = (writes) => [{ nsid: "com.atproto.repo.applyWrites", input: { repo: did, writes } }]; const ctx = ctxWith(store, { a: apply([op("create", "k1"), op("create", "k2")]), b: apply([op("update", "k1"), op("delete", "k2")]), c: apply([op("delete", "k1"), op("delete", "zz")]) }); await runModule(ctx, moduleOf(), "a", {}, pds); assert.deepEqual([...store.rows.keys()], [uri("k1"), uri("k2")]); assert.equal(logOf(await runModule(ctx, moduleOf(), "b", {}, pds))[0].ok, true); assert.deepEqual([...store.rows.keys()], [uri("k1")]); const c = await runModule(ctx, moduleOf(), "c", {}, pds); assert.match(logOf(c)[0].error, /zz was not created/); assert.ok(store.rows.has(uri("k1")), "a refused applyWrites changes nothing"); }); test("a pin loads the version publish keeps at .<32 hex>, so a republish leaves pinned compositions as they were", async () => { const { loadComposition } = await import("../compose/index.js"); const URI = "at://did:plc:pub/com.fedfork.exec.wasm.module/m"; const blob = "bafkreie5737gdxlw5i64vzichcalba3z2v5n6icifvx5xytvske7mr3hpm"; const records = new Map(); // rkey -> value const ctx = { http: { fetch: async (url) => { if (url.startsWith("https://plc.directory/")) return Response.json({ service: [{ id: "#atproto_pds", serviceEndpoint: "https://pds.example" }] }); if (url.includes("getRecord")) { const value = records.get(new URL(url).searchParams.get("rkey")); return value ? Response.json({ cid: "bafyrecord", value }) : Response.json({ error: "RecordNotFound" }, { status: 400 }); } return new Response(new Uint8Array([0, 97, 115, 109])); }, }, }; const publish = async (calls) => { const value = { abi: "emdash-wasm-json-v1", module: { ref: { $link: blob } }, actions: [], calls }; const pin = await modulePin({ module: new Uint8Array([0, 97, 115, 109]), calls }); records.set(`m.${pin.slice(0, 32)}`, value).set("m", value); return pin; }; const pin = await publish(["a.b.c"]); const manifest = { instances: [{ name: "a", module: URI, pin }] }; await publish(["x.y.z"]); assert.deepEqual((await loadModule(ctx, URI)).calls, ["x.y.z"], "unpinned: the latest"); const { modules } = await loadComposition(ctx, manifest); assert.deepEqual([modules.a.calls, modules.a.id], [["a.b.c"], URI], "pinned: its version, its id the module's"); assert.deepEqual((await loadModule(ctx, `did:plc:pub/m@${pin.slice(0, 32)}`)).calls, ["a.b.c"]); await assert.rejects(loadModule(ctx, URI, "0".repeat(64)), new RegExp(`${URI}: pin 0{64} not published \\(${URI}\\.0{32} not found\\)`)); });