// Test vectors for the policy modules (crates/policy), ported from // socialweb-computer-kcp atlibs-bidder-fixes-rc159: internal/policyengine/policytest/cases.go // (TrustCases: the expected Vouch / OnlyMe / Mutuals verdict per world) and records.go (how each // world's records look). The kcp spec tests (market/bidder|requester/policy_spec_test.go) run every // case through the scope and full runs of each policy; trustSuite does the same against the wasm, // serving the world's records to the module's getRecord reads. import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { test } from "node:test"; import { load, now } from "../../../atlibs/rust/src/harness.mjs"; const T = "com.publicdomainrelay.temp"; export const NSID = { vouch: "sh.tangled.graph.vouch", badge: `${T}.badgeBlueKeys`, association: `${T}.market.association`, bid: `${T}.market.bid`, accept: `${T}.market.accept`, receipt: `${T}.market.receipt`, rfp: `${T}.market.rfp`, vm: `${T}.compute.vm`, free: `${T}.market.bids.free`, x402: `${T}.market.bids.x402`, vmDelete: `${T}.compute.events.vm.delete`, vmTerminated: `${T}.compute.events.vm.terminated`, }; export const GET_RECORD = "com.atproto.repo.getRecord"; export const Bidder = "did:plc:policytestbidder"; export const BidderOperator = "did:plc:policytestbidop"; export const Requester = "did:plc:policytestrequester"; export const ReqOperator = "did:plc:policytestreqop"; export const Stranger = "did:plc:policyteststranger"; export const OtherBidder = "did:plc:policytestbidder2"; const createdAt = "2026-10-30T00:00:00Z"; const BIDDER_ASSOCIATE = "bidder_associate"; const REQUESTER_ASSOCIATE = "requester_associate"; const sha256 = (...parts) => createHash("sha256").update(Buffer.concat(parts.map((p) => Buffer.from(p)))).digest(); export const claimRKey = (service, subject) => `${service}-${subject.replaceAll(":", "-")}`; const receiptRKey = (uri, cid) => `receipt-${sha256(`${uri.trim()}\n${cid.trim()}`).subarray(0, 16).toString("hex")}`; const releaseRKey = (receipt) => { const alphabet = "234567abcdefghijklmnopqrstuvwxyz"; return [...sha256("delete", [0], receipt).subarray(0, 13)].map((b) => alphabet[b % alphabet.length]).join(""); }; const terminationRKey = (receipt) => `termination-payload-${sha256(`terminated:${receipt}`).subarray(0, 16).toString("hex")}`; const plus = (ms) => new Date(Date.parse(now) + ms).toISOString(); export function partiesFor(perspective) { return perspective === "requester" ? { Self: Requester, SelfOp: ReqOperator, SelfSvc: REQUESTER_ASSOCIATE, CP: Bidder, CPOp: BidderOperator, CPSvc: BIDDER_ASSOCIATE } : { Self: Bidder, SelfOp: BidderOperator, SelfSvc: BIDDER_ASSOCIATE, CP: Requester, CPOp: ReqOperator, CPSvc: REQUESTER_ASSOCIATE }; } // policytest.World: records by at-uri, and the getRecord answers a host would give for them. export class World { records = new Map(); reads = []; put(repo, collection, rkey, value) { const uri = `at://${repo}/${collection}/${rkey}`; const cid = `bafy${sha256(JSON.stringify(value)).toString("hex").slice(0, 20)}`; this.records.set(uri, { uri, cid, value }); return { uri, cid }; } vouch(voucher, subject) { return this.put(voucher, NSID.vouch, subject, { $type: NSID.vouch, subject, createdAt }); } denounce(voucher, subject) { return this.put(voucher, NSID.vouch, subject, { $type: NSID.vouch, subject, kind: "denounce", createdAt }); } mirror(subject, operator, service) { return this.put(subject, NSID.badge, "association", { $type: NSID.badge, service, keyId: subject, challenge: operator, createdAt }); } claim(operator, subject, service) { return this.put(operator, NSID.badge, claimRKey(service, subject), { $type: NSID.badge, service, keyId: subject, challenge: operator, createdAt }); } associate(subject, operator, service) { this.mirror(subject, operator, service); this.claim(operator, subject, service); } heldContract(operator, bidder) { const bid = this.put(bidder, NSID.bid, "policytest-bid", { $type: NSID.bid, createdAt }); const accept = this.put(operator, NSID.accept, "policytest-accept", { $type: NSID.accept, bid, createdAt }); const receipt = this.put(bidder, NSID.receipt, receiptRKey(accept.uri, accept.cid), { $type: NSID.receipt, accept, createdAt }); return { accept, receipt, bidder }; } contractAssociation(subject, operator, service, contract, expiresAt) { this.mirror(subject, operator, service); return this.put(operator, NSID.association, claimRKey(service, subject), { $type: NSID.association, subject, service, contract: contract.accept, expiresAt, createdAt, }); } release(operator, contract) { this.put(operator, NSID.vmDelete, releaseRKey(contract.receipt.uri), { $type: NSID.vmDelete, createdAt }); } terminate(contract) { this.put(contract.bidder, NSID.vmTerminated, terminationRKey(contract.receipt.uri), { $type: NSID.vmTerminated, createdAt }); } bid(bidder, rkey, free, cost = 0) { const nsid = free ? NSID.free : NSID.x402; const payload = this.put(bidder, nsid, `${rkey}-payload`, free ? { $type: nsid, reason: "free", createdAt } : { $type: nsid, cost, createdAt }); return this.put(bidder, NSID.bid, rkey, { $type: NSID.bid, payload, createdAt }); } // The run-module call contract for a policy module: public getRecord on the repo's PDS. respond = (call) => { assert.equal(call.nsid, GET_RECORD, `unexpected call ${call.nsid}`); const { repo, collection, rkey } = call.params; assert.equal(call.service, repo, "a read goes to the repo's own PDS"); const uri = `at://${repo}/${collection}/${rkey}`; this.reads.push(uri); const record = this.records.get(uri); return record ? { ok: true, output: record } : { ok: false, error: `${GET_RECORD} failed with RecordNotFound: Could not locate record: ${uri}` }; }; } // cases.go TrustCases, verbatim. export const TrustCases = [ { name: "unvouched", build: () => {} }, { name: "vouched-by-self", Vouch: true, build: (w, p) => w.vouch(p.Self, p.CP) }, { name: "vouched-by-verified-self-operator", Vouch: true, build: (w, p) => (w.associate(p.Self, p.SelfOp, p.SelfSvc), w.vouch(p.SelfOp, p.CP)) }, { name: "vouched-by-self-claimed-self-operator", build: (w, p) => (w.mirror(p.Self, p.SelfOp, p.SelfSvc), w.vouch(p.SelfOp, p.CP)) }, { name: "verified-counterparty-operator-vouched-by-self", Vouch: true, build: (w, p) => (w.associate(p.CP, p.CPOp, p.CPSvc), w.vouch(p.Self, p.CPOp)) }, { name: "verified-counterparty-operator-vouched-by-self-operator", Vouch: true, build: (w, p) => { w.associate(p.Self, p.SelfOp, p.SelfSvc); w.associate(p.CP, p.CPOp, p.CPSvc); w.vouch(p.SelfOp, p.CPOp); } }, { name: "forged-counterparty-operator-claim", build: (w, p) => (w.vouch(p.Self, p.CPOp), w.mirror(p.CP, p.CPOp, p.CPSvc)) }, { name: "claim-for-the-other-role", build: (w, p) => (w.vouch(p.Self, p.CPOp), w.associate(p.CP, p.CPOp, p.SelfSvc)) }, { name: "vouched-directly-with-verified-operator", Vouch: true, build: (w, p) => (w.associate(p.CP, p.CPOp, p.CPSvc), w.vouch(p.Self, p.CP)) }, { name: "counterparty-operator-vouches-self-only", build: (w, p) => (w.associate(p.CP, p.CPOp, p.CPSvc), w.vouch(p.CPOp, p.Self)) }, { name: "mutual-operator-vouches", Vouch: true, Mutuals: true, build: (w, p) => { w.associate(p.CP, p.CPOp, p.CPSvc); w.vouch(p.Self, p.CPOp); w.vouch(p.CPOp, p.Self); } }, { name: "denounced", build: (w, p) => w.denounce(p.Self, p.CP) }, { name: "stranger-vouches", build: (w, p) => (w.vouch(Stranger, p.CP), w.vouch(p.CP, p.Self)) }, { name: "same-verified-operator", OnlyMe: true, Vouch: true, Mutuals: true, build: (w, p) => (w.associate(p.Self, p.SelfOp, p.SelfSvc), w.associate(p.CP, p.SelfOp, p.CPSvc)) }, { name: "counterparty-operated-by-self", OnlyMe: true, Vouch: true, Mutuals: true, build: (w, p) => w.associate(p.CP, p.Self, p.CPSvc) }, { name: "forged-same-operator", build: (w, p) => (w.associate(p.Self, p.SelfOp, p.SelfSvc), w.mirror(p.CP, p.SelfOp, p.CPSvc)) }, { name: "different-verified-operators", build: (w, p) => (w.associate(p.Self, p.SelfOp, p.SelfSvc), w.associate(p.CP, p.CPOp, p.CPSvc)) }, { name: "contract-scoped-association-held", OnlyMe: true, Vouch: true, Mutuals: true, build: (w, p) => { w.associate(p.Self, p.SelfOp, p.SelfSvc); w.contractAssociation(p.CP, p.SelfOp, p.CPSvc, w.heldContract(p.SelfOp, OtherBidder), plus(3600e3)); } }, { name: "contract-scoped-association-expired", build: (w, p) => { w.associate(p.Self, p.SelfOp, p.SelfSvc); w.contractAssociation(p.CP, p.SelfOp, p.CPSvc, w.heldContract(p.SelfOp, OtherBidder), plus(-60e3)); } }, { name: "contract-scoped-association-released", build: (w, p) => { w.associate(p.Self, p.SelfOp, p.SelfSvc); const contract = w.heldContract(p.SelfOp, OtherBidder); w.contractAssociation(p.CP, p.SelfOp, p.CPSvc, contract, plus(3600e3)); w.release(p.SelfOp, contract); } }, { name: "contract-scoped-association-terminated", build: (w, p) => { w.associate(p.Self, p.SelfOp, p.SelfSvc); const contract = w.heldContract(p.SelfOp, OtherBidder); w.contractAssociation(p.CP, p.SelfOp, p.CPSvc, contract, plus(3600e3)); w.terminate(contract); } }, ]; const FAMILY = { "tangled-vouch": { want: (c) => !!c.Vouch, msg: "not vouched" }, "only-me": { want: (c) => !!c.OnlyMe, msg: "operator mismatch" }, mutuals: { want: (c) => !!c.Mutuals, msg: "not mutual follows" }, open: { want: () => true }, }; export const wasm = (crate) => new URL(`../../target/wasm32-unknown-unknown/release/${crate.replaceAll("-", "_")}.wasm`, import.meta.url); export async function loadPolicy(crate) { const mod = await load(wasm(crate)); // One run of `evaluate` under the real runModule host loop, the world answering its reads. mod.evaluate = async (input, world = new World()) => { const ran = await mod.handle("evaluate", input, { respond: world.respond }); return { ...ran, verdict: ran.result, reads: world.reads }; }; return mod; } export function abiSuite(mod) { test("module has no imports and exports evaluate", () => { assert.equal(WebAssembly.Module.imports(mod.module).length, 0); const names = WebAssembly.Module.exports(mod.module).map((e) => e.name); for (const name of ["memory", "alloc", "evaluate"]) assert.ok(names.includes(name), name); }); } // Every TrustCase, scope and full, from the policy's own perspective, read from the records. export function trustSuite(crate, name, family) { const perspective = name.startsWith("bidder-") ? "bidder" : "requester"; const { want, msg } = FAMILY[family]; return async () => { const mod = await loadPolicy(crate); abiSuite(mod); for (const tc of TrustCases) { for (const mode of ["scope", "full"]) { test(`${name} ${mode} ${tc.name}: allow=${want(tc)}`, async () => { const world = new World(); const p = partiesFor(perspective); tc.build(world, p); const input = mode === "scope" ? { selfDid: p.Self, counterpartyDid: p.CP, mode } : { selfDid: p.Self, counterpartyDid: p.CP, subjectDid: p.CP, mode }; const { verdict, error } = await mod.evaluate(input, world); assert.equal(error, undefined); const deny = mode === "scope" ? `scope denied by ${name}` : msg; assert.deepEqual(verdict, want(tc) ? { allow: true, violations: [] } : { allow: false, violations: [{ msg: deny, policyId: name }] }); }); } } if (family === "open") return; test(`${name}: a seeded snapshot is used as is, no reads`, async () => { const p = partiesFor(perspective); const vouched = { operatorOf: { [p.Self]: p.Self }, vouchedBy: { [p.Self]: [p.CP] } }; const verdict = mod.run("evaluate", { selfDid: p.Self, counterpartyDid: p.CP, snapshot: vouched, now, state: null, event: { type: "start" } }); assert.deepEqual(verdict.calls, undefined); assert.equal(verdict.done, true); assert.equal(verdict.result.allow, family === "tangled-vouch"); const operated = { operatorOf: { [p.Self]: p.SelfOp, [p.CP]: p.SelfOp }, vouchedBy: {} }; assert.equal(mod.run("evaluate", { selfDid: p.Self, counterpartyDid: p.CP, snapshot: operated, now, event: { type: "start" } }).result.allow, true); }); test(`${name}: a self-vouch is ignored (BuildSnapshotWith skips voucher == subject)`, async () => { // The counterparty is the evaluator's own (verified) operator, and only vouches for itself. const p = partiesFor(perspective); const world = new World(); world.associate(p.Self, p.SelfOp, p.SelfSvc); world.vouch(p.SelfOp, p.SelfOp); const { verdict, reads } = await mod.evaluate({ selfDid: p.Self, counterpartyDid: p.SelfOp, mode: "scope" }, world); assert.equal(verdict.allow, false); assert.ok(!reads.includes(`at://${p.SelfOp}/${NSID.vouch}/${p.SelfOp}`), "the self pair is never read"); const seeded = { operatorOf: { [p.Self]: p.SelfOp }, vouchedBy: { [p.Self]: [], [p.SelfOp]: [p.SelfOp] } }; assert.equal(mod.run("evaluate", { selfDid: p.Self, counterpartyDid: p.SelfOp, snapshot: seeded, now, event: { type: "start" } }).result.allow, false); }); test(`${name}: bad input is an error (kcp exits 1), as data`, async () => { assert.equal((await mod.evaluate({ counterpartyDid: Bidder })).error, "selfDid is required (the evaluator's own DID)"); assert.equal((await mod.evaluate({ selfDid: Bidder, mode: "scope" })).error, "scope mode requires counterpartyDid"); assert.deepEqual((await mod.evaluate({ selfDid: Bidder })).verdict, { allow: false, violations: [{ msg: "no counterparty to evaluate", policyId: name }] }); assert.deepEqual((await mod.evaluate({ selfDid: Bidder, subjectDid: Requester, counterpartyDid: Stranger })).verdict, { allow: false, violations: [{ msg: "the subject and the counterparty differ", policyId: name }], }); }); test(`${name}: full mode derives the counterparty from the records`, async () => { const p = partiesFor(perspective); const world = new World(); world.vouch(p.Self, p.CP); const record = (repo, collection) => ({ uri: `at://${repo}/${collection}/r`, cid: "bafyx" }); const input = perspective === "requester" ? { bid: record(p.CP, NSID.bid) } : { rfp: record(p.CP, NSID.rfp) }; const { verdict } = await mod.evaluate({ selfDid: p.Self, ...input }, world); assert.equal(verdict.allow, family === "tangled-vouch"); }); }; }