50 lines
1.7 KiB
JavaScript
50 lines
1.7 KiB
JavaScript
import { createHash } from "node:crypto";
|
|
import { readFile, writeFile } from "node:fs/promises";
|
|
|
|
const request = JSON.parse(await readFile("/input/request.json", "utf8"));
|
|
const [a, b] = request.reports ?? [];
|
|
if (
|
|
!a ||
|
|
!b ||
|
|
a.workerId !== "worker-a" ||
|
|
b.workerId !== "worker-b" ||
|
|
a.imageDigest === b.imageDigest ||
|
|
a.toolchain === b.toolchain ||
|
|
a.inputDigest !== b.inputDigest ||
|
|
a.checkId !== b.checkId ||
|
|
a.normalizedOutputDigest !== b.normalizedOutputDigest ||
|
|
JSON.stringify(a.normalizedMembers) !== JSON.stringify(b.normalizedMembers) ||
|
|
a.verdict !== "pass" ||
|
|
b.verdict !== "pass"
|
|
)
|
|
throw new Error("Independent worker evidence does not agree.");
|
|
const rules = request.rules;
|
|
if (!Array.isArray(rules) || rules.length === 0)
|
|
throw new Error("Matcher rules are required.");
|
|
const appliedRuleIds = rules
|
|
.map((rule) => rule.id)
|
|
.sort((left, right) => Buffer.from(left).compare(Buffer.from(right)));
|
|
if (
|
|
new Set(appliedRuleIds).size !== appliedRuleIds.length ||
|
|
rules.some((rule) => !Array.isArray(rule.deniedMemberDigests))
|
|
)
|
|
throw new Error("Matcher rules are invalid.");
|
|
const denied = new Set(rules.flatMap((rule) => rule.deniedMemberDigests));
|
|
if (a.normalizedMembers.some((member) => denied.has(member)))
|
|
throw new Error("Privacy rule matched normalized evidence.");
|
|
const result = {
|
|
schema: "portfolio-privacy-matcher-result/v1",
|
|
inputDigest: a.inputDigest,
|
|
checkId: a.checkId,
|
|
normalizedOutputDigest: a.normalizedOutputDigest,
|
|
normalizedMembers: a.normalizedMembers,
|
|
ruleSetDigest: request.ruleSetDigest,
|
|
appliedRuleIds,
|
|
verdict: "pass",
|
|
workerImageDigests: [a.imageDigest, b.imageDigest],
|
|
};
|
|
await writeFile("/output/result.json", JSON.stringify(result), {
|
|
flag: "wx",
|
|
mode: 0o400,
|
|
});
|