import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { test } from "node:test"; import { runModule } from "../../../atlibs/javascript/src/run-module/index.js"; import { did, load, now } from "../../../atlibs/rust/src/harness.mjs"; const { module, run } = await load(new URL("../../target/wasm32-unknown-unknown/release/marque.wasm", import.meta.url)); const spec = JSON.parse(await readFile(new URL("./module.json", import.meta.url), "utf8")); // The harness's handle() with module.json's grants: its calls, and anyRecords (the zones Marque wrote). async function runHandle(entry, input, { respond }) { const ctx = { wasm: { run: async ({ entry, input }) => run(entry, { ...input, now }) } }; const call = async (nsid, request) => { const answer = await respond({ nsid, ...request }); if (answer?.ok === false) throw new Error(answer.error ?? "call failed"); return answer?.output; }; return runModule(ctx, { module, calls: spec.calls, anyRecords: spec.anyRecords }, entry, { did, ...input }, call); } const ENTRIES = ["list_domains", "list_records", "create_record", "update_record", "delete_record"]; const start = (fields) => ({ did, now, ...fields, state: null, event: { type: "start" } }); // Fixtures in the shapes Marque publishes (at.marque.domain / at.marque.dns, keyed by the FQDN). const domainUri = `at://${did}/at.marque.domain/example.com`; const zoneUri = `at://${did}/at.marque.dns/example.com`; const domain = { uri: domainUri, cid: "bafydomain2", value: { $type: "at.marque.domain", domain: "example.com", status: "active", registeredAt: now, expiresAt: now, createdAt: now, nameServers: ["stratus.mqdns.de", "cirrus.mqdns.at", "nimbus.mqdns.app"] }, }; const records = [ { ttl: 60, name: "@", value: "192.0.2.1", recordType: "A" }, { ttl: 300, name: "www", value: "example.com", recordType: "CNAME" }, { ttl: 3600, name: "@", value: "mail.example.com", recordType: "MX", priority: 10 }, ]; const zone = { uri: zoneUri, cid: "bafyzone1", value: { $type: "at.marque.dns", baseRevision: 7, domain: "example.com", subject: { uri: domainUri, cid: "bafydomain1" }, records, createdAt: "2026-01-01T00:00:00.000Z" }, }; const notFound = { ok: false, error: "com.atproto.repo.getRecord failed with RecordNotFound: Could not locate record" }; // A PDS holding the domain and (unless zone is null) its zone; records writes. function pds({ zone: z = zone, owned = true, write } = {}) { const writes = []; const reads = []; const respond = ({ nsid, params, input, service }) => { if (nsid === "com.atproto.repo.getRecord") reads.push([params.collection, params.rkey, service]); if (nsid === "com.atproto.repo.getRecord") { if (params.collection === "at.marque.domain") return owned ? { ok: true, output: domain } : notFound; return z ? { ok: true, output: z } : notFound; } writes.push({ nsid, input }); return write ?? { ok: true, output: { uri: zoneUri, cid: "bafyzone2" } }; }; return { respond, writes, reads }; } test("module has no imports and exports the ABI", () => { assert.equal(WebAssembly.Module.imports(module).length, 0); const names = WebAssembly.Module.exports(module).map((e) => e.name); for (const name of ["memory", "alloc", ...ENTRIES]) assert.ok(names.includes(name), name); }); test("list_domains pages through at.marque.domain as a public read of the account's PDS", async () => { const pages = [{ records: [domain], cursor: "next" }, { records: [{ uri: `at://${did}/at.marque.domain/b.dev`, value: { $type: "at.marque.domain", domain: "b.dev", status: "expired" } }] }]; const calls = []; const ran = await runHandle("list_domains", {}, { respond: (call) => (calls.push(call), { ok: true, output: pages.shift() }) }); assert.deepEqual(calls.map((c) => [c.nsid, c.service, c.params.collection, c.params.cursor ?? null]), [ ["com.atproto.repo.listRecords", did, "at.marque.domain", null], ["com.atproto.repo.listRecords", did, "at.marque.domain", "next"], ]); assert.deepEqual(ran.result.domains.map((d) => [d.domain, d.status, d.uri, d.$type]), [ ["example.com", "active", domainUri, undefined], ["b.dev", "expired", `at://${did}/at.marque.domain/b.dev`, undefined], ]); }); test("list_records reads the domain and its zone", async () => { const { respond, reads } = pds(); const ran = await runHandle("list_records", { domain: "Example.com" }, { respond }); assert.deepEqual(ran.result, { domain: "example.com", status: "active", uri: zoneUri, cid: "bafyzone1", records }); assert.deepEqual(reads, [ ["at.marque.domain", "example.com", did], ["at.marque.dns", "example.com", did], ]); }); test("a domain with no at.marque.domain record in the repo is refused", async () => { const { respond, writes } = pds({ owned: false }); const ran = await runHandle("create_record", { domain: "example.com", name: "x", type: "A", value: "192.0.2.9" }, { respond }); assert.match(ran.error, /not a Marque domain/); assert.equal(writes.length, 0); }); test("create_record puts the whole zone back with swapRecord, keeping Marque's fields", async () => { const { respond, writes } = pds(); const ran = await runHandle("create_record", { domain: "example.com", name: "_ATproto", type: "txt", value: `did=${did}`, ttl: "600" }, { respond }); assert.equal(ran.error, undefined, ran.error); const added = { name: "_atproto", recordType: "TXT", value: `did=${did}`, ttl: 600 }; assert.deepEqual(writes, [ { nsid: "com.atproto.repo.putRecord", input: { repo: did, collection: "at.marque.dns", rkey: "example.com", swapRecord: "bafyzone1", record: { ...zone.value, subject: { uri: domainUri, cid: "bafydomain2" }, records: [...records, added], createdAt: now }, }, }, ]); assert.deepEqual(ran.result, { domain: "example.com", uri: zoneUri, cid: "bafyzone2", record: added, records: 4 }); }); test("create_record starts the zone when there is none", async () => { const { respond, writes } = pds({ zone: null }); const ran = await runHandle("create_record", { domain: "example.com", name: "@", type: "AAAA", value: "2001:DB8:0:0::1" }, { respond }); assert.equal(ran.error, undefined, ran.error); assert.deepEqual(writes, [ { nsid: "com.atproto.repo.createRecord", input: { repo: did, collection: "at.marque.dns", rkey: "example.com", record: { $type: "at.marque.dns", domain: "example.com", subject: { uri: domainUri, cid: "bafydomain2" }, records: [{ name: "@", recordType: "AAAA", value: "2001:db8::1", ttl: 3600 }], createdAt: now }, }, }, ]); }); test("values are normalised per type", async () => { const cases = [ [{ type: "MX", value: "Mail2.Example.com.", priority: 20 }, { value: "mail2.example.com", priority: 20 }], [{ type: "SRV", name: "_sip._tcp", value: "5 5060 sip.example.com.", priority: "1" }, { value: "5 5060 sip.example.com", priority: 1 }], [{ type: "CAA", value: '0 ISSUE "letsencrypt.org"' }, { value: '0 issue "letsencrypt.org"' }], [{ type: "NS", name: "sub", value: "ns1.other.net" }, { value: "ns1.other.net" }], [{ type: "A", name: "*.app", value: " 198.51.100.7 " }, { value: "198.51.100.7", name: "*.app" }], ]; for (const [fields, want] of cases) { const { respond, writes } = pds(); const ran = await runHandle("create_record", { domain: "example.com", name: "x", ...fields }, { respond }); assert.equal(ran.error, undefined, `${JSON.stringify(fields)}: ${ran.error}`); const got = writes[0].input.record.records.at(-1); for (const [k, v] of Object.entries(want)) assert.deepEqual(got[k], v, `${fields.type} ${k}`); } }); test("create_record rejects bad input before any call", () => { const base = start({ domain: "example.com", name: "x", type: "A", value: "192.0.2.1" }); const bad = [ [{ domain: "" }, /domain must be/], [{ domain: "localhost" }, /registered domain/], [{ type: "PTR" }, /type must be one of/], [{ value: "300.1.1.1" }, /IPv4/], [{ type: "AAAA", value: "192.0.2.1" }, /IPv6/], [{ type: "CNAME", value: "not a host" }, /hostname/], [{ type: "MX", value: "mail.example.com" }, /needs a priority/], [{ type: "MX", value: "mail.example.com", priority: 70000 }, /needs a priority/], [{ priority: 1 }, /take no priority/], [{ type: "SRV", value: "5 5060 sip.example.com", priority: 1 }, /_service._proto/], [{ type: "SRV", name: "_sip._tcp", value: "5 sip.example.com", priority: 1 }, /weight port target/], [{ type: "SRV", name: "_sip._tcp", value: "5 99999 sip.example.com", priority: 1 }, /port/], [{ type: "CAA", value: "issue letsencrypt.org" }, /CAA flags|flags tag value/], [{ type: "TXT", value: "a\nb" }, /control characters/], [{ type: "TXT", value: "x".repeat(4097) }, /4096/], [{ type: "CAA", value: `0 issue "${"x".repeat(4096)}"` }, /4096/], [{ type: "NS", name: "@", value: "ns1.other.net" }, /nameservers/], [{ name: "www.example.com." }, /no trailing dot/], [{ name: "a b" }, /name must be/], [{ name: "a.*" }, /name must be/], [{ name: "-x" }, /name must be/], [{ ttl: 0 }, /ttl must be/], [{ ttl: "soon" }, /ttl must be a whole number/], ]; for (const [fields, error] of bad) { const out = run("create_record", { ...base, ...fields }); assert.match(out.error ?? "", error, JSON.stringify(fields)); assert.equal(out.calls, undefined, JSON.stringify(fields)); } assert.ok(run("create_record", base).calls); }); test("create_record refuses duplicates and CNAME clashes", async () => { for (const [fields, error] of [ [{ name: "@", type: "A", value: "192.0.2.1" }, /already exists/], [{ name: "WWW", type: "A", value: "192.0.2.5" }, /CNAME cannot share/], [{ name: "@", type: "CNAME", value: "other.example.net" }, /CNAME cannot share/], ]) { const { respond, writes } = pds(); const ran = await runHandle("create_record", { domain: "example.com", ...fields }, { respond }); assert.match(ran.error, error, JSON.stringify(fields)); assert.equal(writes.length, 0); } }); test("update_record changes one record in place, keeping what is not given", async () => { const { respond, writes } = pds(); const ran = await runHandle("update_record", { domain: "example.com", name: "@", type: "mx", value: "MAIL.example.com.", newValue: "mx.example.net", ttl: "" }, { respond }); assert.equal(ran.error, undefined, ran.error); const changed = { name: "@", recordType: "MX", value: "mx.example.net", ttl: 3600, priority: 10 }; assert.deepEqual(writes[0].input.record.records, [records[0], records[1], changed]); assert.equal(writes[0].input.swapRecord, "bafyzone1"); assert.deepEqual(ran.result.record, changed); const renamed = pds(); const out = await runHandle("update_record", { domain: "example.com", name: "@", type: "A", value: "192.0.2.1", newName: "api", ttl: 120 }, { respond: renamed.respond }); assert.deepEqual(renamed.writes[0].input.record.records[0], { name: "api", recordType: "A", value: "192.0.2.1", ttl: 120 }); assert.equal(out.result.records, 3); }); test("update_record checks the new record against the rest of the zone", async () => { const { respond, writes } = pds(); const ran = await runHandle("update_record", { domain: "example.com", name: "@", type: "A", value: "192.0.2.1", newName: "www" }, { respond }); assert.match(ran.error, /CNAME cannot share/); const missing = await runHandle("update_record", { domain: "example.com", name: "@", type: "A", value: "192.0.2.99", newValue: "192.0.2.2" }, { respond }); assert.match(missing.error, /no A record @ 192.0.2.99/); const badNew = await runHandle("update_record", { domain: "example.com", name: "@", type: "A", value: "192.0.2.1", newValue: "nope" }, { respond }); assert.match(badNew.error, /IPv4/); assert.equal(writes.length, 0); }); test("delete_record removes exactly one record", async () => { const { respond, writes } = pds(); const ran = await runHandle("delete_record", { domain: "example.com", name: "www", type: "CNAME", value: "Example.com." }, { respond }); assert.equal(ran.error, undefined, ran.error); assert.deepEqual(writes[0].input.record.records, [records[0], records[2]]); assert.deepEqual(ran.result, { domain: "example.com", uri: zoneUri, cid: "bafyzone2", record: records[1], records: 2 }); assert.match(run("delete_record", start({ domain: "example.com", name: "www", type: "CNAME" })).error, /value is required/); const none = pds({ zone: null }); assert.match((await runHandle("delete_record", { domain: "example.com", name: "www", type: "CNAME", value: "example.com" }, { respond: none.respond })).error, /no CNAME record/); }); test("a concurrent edit (swapRecord mismatch) is reported, not overwritten", async () => { const { respond } = pds({ write: { ok: false, error: "com.atproto.repo.putRecord failed with InvalidSwap: Record was at bafyother" } }); const ran = await runHandle("create_record", { domain: "example.com", name: "x", type: "A", value: "192.0.2.9" }, { respond }); assert.match(ran.error, /changed while editing it, try again/); }); test("other read errors end the run", async () => { const ran = await runHandle("list_records", { domain: "example.com" }, { respond: () => ({ ok: false, error: "getRecord failed with 500" }) }); assert.match(ran.error, /500/); });