← Files ModRetro Chromatic PluginARCHIVED FILE
dist/recording-location.js
7.48 KB · Oct 5, 2026 · 18:37 UTC
import { createHash } from "node:crypto";
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync, readdirSync, realpathSync } from "node:fs";
import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
const MAX_BYTES = 512 * 1024 * 1024;
const MAX_ENTRIES = 20_000;
const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
const inside = (root, path) => path === root || path.startsWith(root + sep);
function unchanged(a, b) {
return ["dev", "ino", "mode", "uid", "gid", "nlink", "size", "mtimeMs", "ctimeMs"].every(key => a[key] === b[key]);
}
function owned(st) {
if (!process.getuid || st.uid !== process.getuid() || (st.mode & 0o7022) !== 0 || st.isSymbolicLink()) {
throw new Error("Recording archive requires owned paths without special or writable-by-others permission bits");
}
}
function bytes(path, maximum) {
const before = lstatSync(path);
owned(before);
if (!before.isFile() || before.nlink !== 1 || before.size > maximum)
throw new Error("Invalid archive metadata file");
const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
try {
if (!unchanged(before, fstatSync(fd)))
throw new Error("Archive metadata identity changed");
const out = Buffer.alloc(before.size + 1);
let size = 0;
let n;
while ((n = readSync(fd, out, size, out.length - size, null)) > 0) {
size += n;
if (size > before.size)
throw new Error("Archive metadata grew");
}
if (size !== before.size || !unchanged(before, fstatSync(fd)) || !unchanged(before, lstatSync(path)))
throw new Error("Archive metadata changed");
return out.subarray(0, size);
}
finally {
closeSync(fd);
}
}
/** One canonical inventory shared by maintenance and the ordinary TS reader. */
export function recordingInventory(root, resolvePath) {
if (resolvePath(root, { existing: true }) !== root || realpathSync(root) !== root)
throw new Error("Archive root is redirected");
const rows = [];
let total = 0;
let count = 0;
const visit = (path) => {
const before = lstatSync(path);
owned(before);
if (++count > MAX_ENTRIES)
throw new Error("Recording member limit exceeded");
const name = relative(root, path);
if (before.isDirectory()) {
rows.push([name, "directory", before.mode & 0o7777]);
for (const child of readdirSync(path).sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b))))
visit(join(path, child));
}
else {
if (!before.isFile() || before.nlink !== 1)
throw new Error("Recording contains a linked or non-regular member");
total += before.size;
if (total > MAX_BYTES)
throw new Error("Recording archive byte limit exceeded");
const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
try {
if (!unchanged(before, fstatSync(fd)))
throw new Error("Recording member identity changed");
const hash = createHash("sha256");
const buffer = Buffer.alloc(65536);
let n;
let size = 0;
while ((n = readSync(fd, buffer)) > 0) {
size += n;
if (size > before.size)
throw new Error("Recording member grew");
hash.update(buffer.subarray(0, n));
}
if (size !== before.size || !unchanged(before, fstatSync(fd)))
throw new Error("Recording member changed");
rows.push([name, "file", before.mode & 0o7777, size, hash.digest("hex")]);
}
finally {
closeSync(fd);
}
}
if (!unchanged(before, lstatSync(path)))
throw new Error("Recording changed during inventory");
};
visit(root);
for (const marker of [".gitignore", ".npmignore"])
if (!bytes(join(root, marker), 2).equals(Buffer.from("*\n")))
throw new Error("Recording package-protection marker differs");
return { digest: digest(JSON.stringify(rows)), bytes: total, entries: count };
}
/** A mapping is not a generic accounting override: authenticate both copies,
* the original reference, manifest, and every retained byte/mode first. */
export function recordingArchiveOrigin(root, resolvePath) {
const container = dirname(root);
const archiveRoot = dirname(container);
if (basename(root) !== "recording" || basename(archiveRoot) !== "recording-archives" || basename(dirname(archiveRoot)) !== "artifacts")
return undefined;
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(basename(container)))
throw new Error("Invalid archive container identity");
const mappingPath = join(container, "mapping.json");
if (resolvePath(mappingPath, { existing: true }) !== mappingPath || realpathSync(mappingPath) !== mappingPath)
throw new Error("Archive mapping is redirected");
const raw = bytes(mappingPath, 4096);
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(raw));
if (!value || typeof value !== "object" || Array.isArray(value)
|| Object.keys(value).sort().join() !== "archivePath,inventory,manifestSha256,originalPath,schemaVersion,sessionId"
|| value.schemaVersion !== 1 || value.archivePath !== root || typeof value.originalPath !== "string" || !isAbsolute(value.originalPath)
|| !/^[0-9a-f]{32}$/u.test(value.sessionId) || !/^[0-9a-f]{64}$/u.test(value.manifestSha256))
throw new Error("Invalid archive mapping");
const original = value.originalPath;
if (inside(archiveRoot, original) || inside(original, archiveRoot) || resolvePath(original, { existing: true }) !== original || realpathSync(original) !== original)
throw new Error("Invalid original recording reference");
const before = lstatSync(original);
owned(before);
if (!before.isDirectory() || (before.mode & 0o7777) !== 0o700 || readdirSync(original).sort().join() !== ".gitignore,.npmignore,.recording-archive.json")
throw new Error("Archive reference directory differs");
for (const marker of [".gitignore", ".npmignore"])
if (!bytes(join(original, marker), 2).equals(Buffer.from("*\n")))
throw new Error("Archive reference marker differs");
const pointer = join(original, ".recording-archive.json");
if ((lstatSync(mappingPath).mode & 0o7777) !== 0o600 || (lstatSync(pointer).mode & 0o7777) !== 0o600 || !bytes(pointer, 4096).equals(raw))
throw new Error("Archive mapping copies differ");
const inventory = recordingInventory(root, resolvePath);
if (JSON.stringify(inventory) !== JSON.stringify(value.inventory))
throw new Error("Archived recording bytes or modes changed");
const manifest = bytes(join(root, "recording.json"), 1024 * 1024);
if (digest(manifest) !== value.manifestSha256 || JSON.parse(manifest.toString("utf8")).sessionId !== value.sessionId)
throw new Error("Archived recording provenance changed");
if (!unchanged(before, lstatSync(original)) || !bytes(mappingPath, 4096).equals(raw) || !bytes(pointer, 4096).equals(raw))
throw new Error("Archive mapping changed during reading");
return original;
}
//# sourceMappingURL=recording-location.js.mapSHA-256: ead99e754093d8745d3d6d5ab68b2cd8cbf526bcb9e8bf9f68e1aa2c6fadc188