// Copyright 2026 Richard Andresik. SPDX-License-Identifier: Apache-2.0 // This tool reads two explicit sources and emits a patch or verifies their bytes. // It never edits files, accesses credentials, or traverses the project tree. import { createHash } from "node:crypto"; import { readFile } from "node:fs/promises"; import { resolve } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { isDeepStrictEqual } from "node:util"; const root = fileURLToPath(new URL("../", import.meta.url)); const ranges = [ ["module-integration", "function textE2eeSupported()", "function readStoredPair(storage, key)"], ["file-buffers", "function fileByteLength(data)", "function scheduleReconnect(delay)"], ["file-controller", "function createFileTransferController()", "function setupWsServer()"] ]; const banner = "// Copyright 2026 Richard Andresik. SPDX-License-Identifier: Apache-2.0\n" + "// Review snapshot: exact excerpts from IcyZip's browser client.\n" + "// These functions require application state or the supplied test adapter.\n" + "// See THREAT-MODEL.md before relying on this protocol.\n\n"; export function sha256(value) { return createHash("sha256").update(value).digest("hex"); } export function extract(source, moduleSource) { if (typeof source !== "string" || typeof moduleSource !== "string") throw new Error("Both browser integration and protocol module sources are required."); const sections = ranges.map(function ([name, startAnchor, endAnchor]) { const start = source.indexOf(startAnchor); const end = source.indexOf(endAnchor, start + startAnchor.length); if (start < 0 || end < start || source.indexOf(startAnchor, start + 1) !== -1 || source.indexOf(endAnchor, end + 1) !== -1) { throw new Error("Missing or ambiguous source boundary: " + name); } const code = source.slice(start, end); return { name, code, startAnchor, endAnchor, firstLine: source.slice(0, start).split("\n").length, bytes: Buffer.byteLength(code), sha256: sha256(code) }; }); const snapshot = banner + sections.map(function (part) { return "// BEGIN exact source section: " + part.name + "\n" + part.code + "// END exact source section: " + part.name + "\n\n"; }).join("").slice(0, -1); return { moduleSource, snapshot, provenance: { format: 2, module: { sourcePath: "client/src/js/e2ee.js", bytes: Buffer.byteLength(moduleSource), sha256: sha256(moduleSource) }, sourcePath: "client/src/js/view/client_wsscript.js", sourceSha256: sha256(source), snapshotSha256: sha256(snapshot), statement: "The protocol module is byte-identical. Integration section bodies are verbatim. The full application and relay are not included.", sections: sections.map(function ({ code, ...part }) { return part; }) } }; } export function verifySource(generated, expected, expectedModule, recorded) { // Full-file hashes and line numbers identify the extraction release, but // unrelated UI edits can change them without changing the reviewed bytes. function reviewProvenance({ sourceSha256, sections, ...provenance }) { return { ...provenance, sections: sections.map(function ({ firstLine, ...section }) { return section; }) }; } if (sha256(expected) !== recorded.snapshotSha256 || generated.snapshot !== expected || generated.moduleSource !== expectedModule || sha256(expectedModule) !== recorded.module.sha256 || !isDeepStrictEqual(reviewProvenance(generated.provenance), reviewProvenance(recorded))) { throw new Error("E2EE snapshot differs from the supplied application source or provenance."); } return { fullSourceMatchesRecordedFile: generated.provenance.sourceSha256 === recorded.sourceSha256, integrationLocationsMatchRecordedFile: generated.provenance.sections.every(function (section, index) { return section.firstLine === recorded.sections[index].firstLine; }) }; } async function main(args) { let sourcePath; let modulePath; let sourceUrl; let mode; for (let index = 0; index < args.length; index += 1) { const arg = args[index]; if (arg === "--source" && !sourcePath) sourcePath = args[++index]; else if (arg === "--module" && !modulePath) modulePath = args[++index]; else if (arg === "--url" && !sourceUrl) sourceUrl = args[++index]; else if ((arg === "--check" || arg === "--patch") && !mode) mode = arg; else throw new Error("Usage: snapshot.mjs (--source CLIENT --module MODULE | --url URL) (--check | --patch)"); } if (!mode || Boolean(sourcePath) === Boolean(sourceUrl) || Boolean(sourcePath) !== Boolean(modulePath)) { throw new Error("Choose exactly one source and one mode."); } let source; let moduleSource; if (sourceUrl) { const url = new URL(sourceUrl); if (url.protocol !== "https:" || url.hostname !== "icyzip.com" || url.pathname !== "/js/view/client_wsscript.js" || url.username || url.password || url.hash || url.search) { throw new Error("Remote checks are limited to the public IcyZip browser asset."); } if (mode !== "--check") throw new Error("Remote sources can only be checked."); async function publicAsset(assetUrl) { const response = await fetch(assetUrl, { headers: { "X-IcyZip-Test-Traffic": "e2ee-source-review" }, redirect: "error", signal: AbortSignal.timeout(30000) }); if (!response.ok) throw new Error("Public asset HTTP status: " + response.status); return response.text(); } source = await publicAsset(url); moduleSource = await publicAsset("https://icyzip.com/js/e2ee.js"); } else { source = await readFile(resolve(sourcePath), "utf8"); moduleSource = await readFile(resolve(modulePath), "utf8"); } if ([source, moduleSource].some(value => Buffer.byteLength(value) > 1024 * 1024)) throw new Error("Source exceeds 1 MiB."); const generated = extract(source, moduleSource); if (mode === "--patch") { const files = [ ["src/e2ee.js", generated.moduleSource], ["src/snapshot.js", generated.snapshot], ["PROVENANCE.json", JSON.stringify(generated.provenance, null, 2) + "\n"] ]; let patch = "*** Begin Patch\n"; for (const [name, content] of files) { const target = resolve(root, name); let previous; try { previous = await readFile(target, "utf8"); } catch (error) { if (error.code !== "ENOENT") throw error; } if (previous === content) continue; if (previous === undefined) patch += "*** Add File: " + target + "\n"; else patch += "*** Update File: " + target + "\n@@\n" + previous.split("\n").slice(0, -1).map(line => "-" + line).join("\n") + "\n"; patch += content.split("\n").slice(0, -1).map(line => "+" + line).join("\n") + "\n"; } process.stdout.write(patch + "*** End Patch\n"); return; } const expected = await readFile(resolve(root, "src/snapshot.js"), "utf8"); const expectedModule = await readFile(resolve(root, "src/e2ee.js"), "utf8"); const recorded = JSON.parse(await readFile(resolve(root, "PROVENANCE.json"), "utf8")); const correspondence = verifySource(generated, expected, expectedModule, recorded); console.log(JSON.stringify({ result: "exact-e2ee-module-and-integration-match", source: sourceUrl ? "public-asset" : "local-file", sections: generated.provenance.sections.length, snapshotSha256: recorded.snapshotSha256, moduleSha256: recorded.module.sha256, ...correspondence })); } if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) { main(process.argv.slice(2)).catch(function (error) { console.error(error.message); process.exitCode = 1; }); }