← Files ModRetro Chromatic PluginARCHIVED FILE

scripts/chromatic-runtime.mjs

32.7 KB · Oct 2, 2026 · 00:37 UTC

↓ Download file

/** Authenticate the embedded vendor files. No discovery, execution or downloads. */
import { createHash } from "node:crypto";
import { accessSync, closeSync, constants, fchmodSync, fstatSync, linkSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { brotliDecompressSync, constants as zlibConstants } from "node:zlib";

export const CHROMATIC_VERSION = "1.2.1";
export const CHROMATIC_ROOT = "third-party/chromatic-cli";
export const CHROMATIC_TARGETS = Object.freeze({
  "darwin-arm64": "darwin-arm64/bin/chromatic-cli",
  "darwin-x64": "darwin-x64/bin/chromatic-cli",
  "linux-arm64-gnu": "linux-arm64-gnu/bin/chromatic-cli",
  "linux-x64-gnu": "linux-x64-gnu/bin/chromatic-cli",
  "win32-arm64": "win32-arm64/bin/chromatic-cli.exe",
  "win32-x64": "win32-x64/bin/chromatic-cli.exe",
});
export const CHROMATIC_MEMBERS = Object.freeze(Object.fromEntries([
  ["NOTICE.md", 1622, "b36d5bcafacb1d4d5a147e64aa87a04c1160c684fe266c25582166537188a893", 0o644],
  ["PROVENANCE.json", 14693, "f691ae561c92ee18029fe196ee9508be4b1b04e4bc061376271a1a907b3cfd43", 0o644],
  ["SBOM.json", 23337, "2eb5aa0dccd244ad32b1653ad4b7e39a2254b3b529aa94a1e581fd4fcb8a5ed0", 0o644],
  ["darwin-arm64/THIRD_PARTY_NOTICES.txt", 1596953, "b3b23000848c1b98e87730b536a9a029ecb17e2ce0d77d8a7e8c19226d571aa7", 0o644],
  ["darwin-arm64/bin/chromatic-cli", 12997184, "37257304b250634c586b0061e6f75dc1bec6ebaa57da1b9937106fa1fd370c70", 0o755],
  ["darwin-x64/THIRD_PARTY_NOTICES.txt", 1596952, "39a847c252406ece8d979455ce1ee061e0bab80357107b25003c01b78db2ab11", 0o644],
  ["darwin-x64/bin/chromatic-cli", 14260892, "4b09e5c0ec0ac0837f1419548aa4a87b8638870a6213b8c9c39b50ac5c8ad0d1", 0o755],
  ["linux-arm64-gnu/THIRD_PARTY_NOTICES.txt", 1560649, "3e31321f07fabffd543e4fdea00c1efdbaf8fe09ae39a14fded8e91d88d4a7f1", 0o644],
  ["linux-arm64-gnu/bin/chromatic-cli", 13374504, "5b5921c0847d965ba9875a5d3db03784193c1a7c377f60bdaa68ccdbfee0958e", 0o755],
  ["linux-x64-gnu/THIRD_PARTY_NOTICES.txt", 1560648, "b17f7e5af481f97ec642aad4ff9f221026758da28e88581ca671f604d69a334b", 0o644],
  ["linux-x64-gnu/bin/chromatic-cli", 14770920, "2791460d17ccb9c16b6d4f0072c01cd49104ea93cb6479ef697b05167a07e6a5", 0o755],
  ["win32-arm64/THIRD_PARTY_NOTICES.txt", 1736104, "318b0cb065a3c872662dcf43cb889b7fcd5518c0c2514bc5b69df2b95a179896", 0o644],
  ["win32-arm64/bin/chromatic-cli.exe", 18366976, "7ad15877071b74d1099608e35bb0364607fcf4f0d9dafbcfdc53097e0dce5e56", 0o644],
  ["win32-x64/THIRD_PARTY_NOTICES.txt", 1736100, "c767650bf16d087dd332f24394d7c3ec3a7f4c9bf13b281db69b7b6fdf1c125f", 0o644],
  ["win32-x64/bin/chromatic-cli.exe", 18786816, "eeddc76b11933d09564570dfc521d13251c6d4048d8190242fdd29e7fe81e51f", 0o644],
].map(([name, size, sha256, mode]) => [name, Object.freeze({ size, sha256, mode })])));
export const CHROMATIC_FILES = Object.freeze(Object.fromEntries(
  Object.entries(CHROMATIC_MEMBERS).map(([name, member]) => [name, member.sha256]),
));
export const CHROMATIC_REQUIRED_PATHS = Object.freeze([
  "scripts/chromatic.mjs", "scripts/chromatic-runtime.mjs",
  ...Object.keys(CHROMATIC_FILES).map((name) => `${CHROMATIC_ROOT}/${name}`),
]);
// This fixed-order stream changes storage, not any supplier executable bytes.
export const CHROMATIC_PACKED = Object.freeze({
  format: "brotli-concat-v1", member: "executables.br",
  source: "assets/chromatic-cli/1.2.1.br",
  size: 15452255, sha256: "73c7da79cd50f7b60dcb90b7f2cbea54f04607a77cdb484baccd2aeac1d66176",
  mode: 0o644, decodedSize: 92557292, windowBytes: 134217728,
  targets: Object.freeze(Object.keys(CHROMATIC_TARGETS)),
});
// V2 keeps the old stream readable and adds independently decoded resources.
export const CHROMATIC_PACKED_V2 = Object.freeze({
  "format": "brotli-concat-v2",
  "member": "executables-v2.br",
  "source": "assets/chromatic-cli/1.2.1-v2.br",
  "size": 15419258,
  "sha256": "fd6a1b542a510f3ee1e047e83d31e1ad96bd4580fe7c59fbc558befba778beae",
  "mode": 420,
  "decodedSize": 92557292,
  "windowBytes": 134217728,
  "targets": [
    "darwin-arm64",
    "linux-arm64-gnu",
    "win32-arm64",
    "darwin-x64",
    "linux-x64-gnu",
    "win32-x64"
  ]
});
Object.freeze(CHROMATIC_PACKED_V2.targets);
export const CHROMATIC_NOTICE_PACK = Object.freeze({
  "member": "notices.br",
  "source": "assets/chromatic-cli/notices-1.2.1.br",
  "size": 24102,
  "sha256": "92e4592cfc2d53ea03aec32b358d1d5d290f2b7702bc6abf4f82d17936c7bb4f",
  "mode": 420,
  "decodedSize": 9787406,
  "windowBytes": 134217728
});
export const CHROMATIC_ARTWORK_PACK = Object.freeze({
  "member": "images.br",
  "source": "assets/chromatic-cli/artwork-v1.br",
  "size": 1088764,
  "sha256": "706479c13dc462355eb4184951d4a58fef9edc3ed47a875a33cbbf7b29e0618d",
  "mode": 420,
  "decodedSize": 1240408,
  "windowBytes": 134217728
});
export const CHROMATIC_ARTWORK_MEMBERS = Object.freeze(Object.fromEntries(Object.entries({
  "chromatic-bubblegum.webp": {
    "size": 148700,
    "sha256": "ac3ccc1a73bcb80f54bebcb8faa8d83c8e703f47b621c37e2c0a8a49f4758873",
    "mode": 420
  },
  "chromatic-cloud.webp": {
    "size": 147432,
    "sha256": "e4a9080466a23208e019007b2ffe516ffa7a42cdc1ac92d78d0904d5edabf7dd",
    "mode": 420
  },
  "chromatic-codex.webp": {
    "size": 147612,
    "sha256": "fc485392a920aee5b546aca91b92fcf6cef1f87ac389171f9f5510ed978670c0",
    "mode": 420
  },
  "chromatic-inferno.webp": {
    "size": 171008,
    "sha256": "3607a9393e0dcf57ed3775639ed6aad1ca5298d085e1234963169ff52f0b5aab",
    "mode": 420
  },
  "chromatic-leaf.webp": {
    "size": 153560,
    "sha256": "0ac4e6bf8f0e6d4006f84c446daf72ba3b25f3d1e55fbe5b342686c490e1b50b",
    "mode": 420
  },
  "chromatic-midnight.webp": {
    "size": 154918,
    "sha256": "32d6e4e4af68baa5de7de76dd11fcf340a48a6be37ad985c6a9586a1228bc03d",
    "mode": 420
  },
  "chromatic-volt.webp": {
    "size": 165532,
    "sha256": "ae2223bb23fc32b1f53a55b54ed80c437301cd62d79590686341c8752529971b",
    "mode": 420
  },
  "chromatic-wave.webp": {
    "size": 151646,
    "sha256": "572803bae96f0d73a2585b92040730d355af797f342e8768766a167e5fbba8c4",
    "mode": 420
  }
}).map(([name, pin]) => [name, Object.freeze(pin)])));
export const CHROMATIC_STORAGE_SOURCES = Object.freeze([CHROMATIC_PACKED.source, CHROMATIC_PACKED_V2.source, CHROMATIC_NOTICE_PACK.source, CHROMATIC_ARTWORK_PACK.source]);

const commonMembers = ["NOTICE.md", "PROVENANCE.json", "SBOM.json"];
function validatedTarget(target) {
  if (typeof target !== "string" || !Object.hasOwn(CHROMATIC_TARGETS, target)) {
    throw new Error("bundledChromaticTarget must be an exact supported Chromatic target.");
  }
  return target;
}

/** Absence keeps the universal bundle; a declared target is never inferred. */
export function chromaticTargetFromManifest(manifest) {
  if (manifest === null || typeof manifest !== "object" || Array.isArray(manifest)) {
    throw new Error("The Chromatic package manifest must be an object.");
  }
  for (const name of ["bundledChromatic", "bundledChromaticTarget", "bundledChromaticFormat"]) {
    if (name in manifest && !Object.hasOwn(manifest, name)) {
      throw new Error(`The Chromatic package manifest must declare its own ${name}.`);
    }
  }
  if (Object.hasOwn(manifest, "bundledChromatic") && manifest.bundledChromatic !== CHROMATIC_VERSION) {
    throw new Error(`Unsupported bundled Chromatic release; expected ${CHROMATIC_VERSION}.`);
  }
  if (!Object.hasOwn(manifest, "bundledChromaticTarget")) return undefined;
  if (manifest.bundledChromatic !== CHROMATIC_VERSION) {
    throw new Error(`bundledChromaticTarget requires bundledChromatic ${CHROMATIC_VERSION}.`);
  }
  return validatedTarget(manifest.bundledChromaticTarget);
}

export function chromaticFormatFromManifest(manifest) {
  const target = chromaticTargetFromManifest(manifest);
  if (!Object.hasOwn(manifest, "bundledChromaticFormat")) return undefined;
  if (![CHROMATIC_PACKED.format, CHROMATIC_PACKED_V2.format].includes(manifest.bundledChromaticFormat) || target !== undefined
      || manifest.bundledChromatic !== CHROMATIC_VERSION) {
    throw new Error("The packed Chromatic format requires the exact universal bundled release.");
  }
  return manifest.bundledChromaticFormat;
}

function executablePack(format) {
  if (format === CHROMATIC_PACKED.format) return CHROMATIC_PACKED;
  if (format === CHROMATIC_PACKED_V2.format) return CHROMATIC_PACKED_V2;
  throw new Error("Unsupported packed Chromatic selection.");
}

function selectedMemberNames(target, format) {
  if (format !== undefined) {
    executablePack(format);
    if (target !== undefined) throw new Error("Unsupported packed Chromatic selection.");
    if (format === CHROMATIC_PACKED_V2.format) return [...commonMembers, CHROMATIC_PACKED_V2.member, CHROMATIC_NOTICE_PACK.member];
    return [...Object.keys(CHROMATIC_FILES).filter((name) => !Object.values(CHROMATIC_TARGETS).includes(name)), CHROMATIC_PACKED.member];
  }
  if (target === undefined) return Object.keys(CHROMATIC_FILES);
  validatedTarget(target);
  return [...commonMembers, `${target}/THIRD_PARTY_NOTICES.txt`, CHROMATIC_TARGETS[target]];
}

/** Packaging selection only; it need not match the packaging host. */
export function chromaticRequiredPaths(target, format) {
  if (target === undefined && format === undefined) return CHROMATIC_REQUIRED_PATHS;
  return Object.freeze([
    "scripts/chromatic.mjs", "scripts/chromatic-runtime.mjs",
    ...selectedMemberNames(target, format).map((name) => `${CHROMATIC_ROOT}/${name}`),
    ...(format === CHROMATIC_PACKED_V2.format ? [`assets/devices/${CHROMATIC_ARTWORK_PACK.member}`] : []),
  ]);
}
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const same = (a, b) => ["dev", "ino", "size", "mode", "nlink", "uid", "gid", "mtimeMs", "ctimeMs"].every((key) => a[key] === b[key]);
// The largest 1.2.1 executable is 18,786,816 bytes. Admit only exact pinned
// members below 24 MiB; size, digest, type and mode checks remain mandatory.
const MAX_MEMBER_BYTES = 24 * 1024 * 1024;
const MAX_MANIFEST_BYTES = 1024 * 1024;
const executableMembers = new Set(Object.values(CHROMATIC_TARGETS));
const allowedModes = (name, member, platform) => platform === "win32" && executableMembers.has(name)
  ? [0o644, 0o755] : [member.mode];

/** Windows does not expose POSIX group/other permission bits faithfully. */
export function chromaticDiskMode(mode, platform = process.platform) {
  return platform === "win32" ? (mode & 0o111 ? 0o755 : 0o644) : mode & 0o777;
}

/** Pure target admission; no external version query, download or PATH fallback. */
export function selectChromaticTarget({ platform = process.platform, arch = process.arch,
  glibcVersion = platform === "linux" ? process.report?.getReport().header?.glibcVersionRuntime : undefined,
} = {}) {
  const target = `${platform}-${arch}${platform === "linux" ? "-gnu" : ""}`;
  if (!Object.hasOwn(CHROMATIC_TARGETS, target)) throw new Error(`No bundled Chromatic CLI is available for ${platform}-${arch}; no fallback is permitted. Other plugin tools remain available.`);
  if (platform === "linux") {
    const version = typeof glibcVersion === "string" && /^(\d+)\.(\d+)(?:\.\d+)*$/u.exec(glibcVersion);
    if (!version || Number(version[1]) < 2 || (Number(version[1]) === 2 && Number(version[2]) < 39)) {
      throw new Error("Bundled Chromatic CLI requires GNU/Linux with glibc 2.39 or newer. musl, an unknown libc, or older glibc is unsupported; no fallback is permitted.");
    }
  }
  return target;
}

/** Universal packages keep unrelated tools available on unsupported hosts. */
export function requireChromaticHostTarget(target, options) {
  if (target === undefined) return undefined;
  validatedTarget(target);
  const host = selectChromaticTarget(options);
  if (target !== host) {
    throw new Error(`The bundled Chromatic target ${target} does not match this host (${host}); no fallback is permitted.`);
  }
  return target;
}

/** Check the actual captured buffers that a preparer will write, not a later read. */
export function verifyChromaticRecords(records, { platform = process.platform, target, format } = {}) {
  const members = new Set(selectedMemberNames(target, format));
  const selected = records.filter((record) => record.path.startsWith(CHROMATIC_ROOT + "/"));
  if (selected.length !== members.size) throw new Error("Captured Chromatic distribution has missing or extra members.");
  const seen = new Set();
  for (const record of selected) {
    const name = record.path.slice(CHROMATIC_ROOT.length + 1);
    const bytes = record.contents ?? record.bytes;
    const member = physicalMember(name, format);
    // Windows may report executable bits for EXEs and omit them for foreign
    // binaries. Only pinned executable members accept both normalized modes;
    // metadata and every POSIX host retain their exact pinned modes.
    if (seen.has(name) || !members.has(name) || !member || !Buffer.isBuffer(bytes) || bytes.length !== member.size || bytes.length > MAX_MEMBER_BYTES ||
        createHash("sha256").update(bytes).digest("hex") !== member.sha256 || !allowedModes(name, member, platform).includes(record.mode)) {
      throw new Error(`Captured Chromatic distribution differs from its pin or mode: ${name}`);
    }
    if (format !== undefined && name === executablePack(format).member) decodeChromaticExecutables(bytes, format);
    if (format === CHROMATIC_PACKED_V2.format && name === CHROMATIC_NOTICE_PACK.member) decodeChromaticNotices(bytes);
    seen.add(name);
  }
  if (format === CHROMATIC_PACKED_V2.format) {
    const artwork = records.filter((record) => record.path === `assets/devices/${CHROMATIC_ARTWORK_PACK.member}`);
    if (artwork.length !== 1 || artwork[0].mode !== CHROMATIC_ARTWORK_PACK.mode) throw new Error("Missing or changed packed device artwork.");
    decodeDeviceArtwork(artwork[0].contents ?? artwork[0].bytes);
  }
}

function physicalMember(name, format) {
  if (format !== undefined && name === executablePack(format).member) return executablePack(format);
  if (format === CHROMATIC_PACKED_V2.format && name === CHROMATIC_NOTICE_PACK.member) return CHROMATIC_NOTICE_PACK;
  return CHROMATIC_MEMBERS[name];
}

/** All storage packs use a fixed reviewed layout, never names or sizes from
 * compressed input. Authenticate before allocating the larger dictionary. */
function decodePack(bytes, pack, layout, copy = false) {
  if (!Buffer.isBuffer(bytes) || bytes.length !== pack.size
      || createHash("sha256").update(bytes).digest("hex") !== pack.sha256) {
    throw new Error(`Packed Chromatic bytes differ from the pinned stream: ${pack.member}`);
  }
  const decoded = brotliDecompressSync(bytes, {
    params: { [zlibConstants.BROTLI_DECODER_PARAM_LARGE_WINDOW]: 1 },
    maxOutputLength: pack.decodedSize, info: true,
  });
  if (decoded.buffer.length !== pack.decodedSize || decoded.engine.bytesWritten !== bytes.length) {
    throw new Error("Packed Chromatic stream has a missing or trailing payload.");
  }
  const members = new Map();
  let offset = 0;
  for (const [name, member] of layout) {
    const contents = decoded.buffer.subarray(offset, offset + member.size);
    if (contents.length !== member.size || member.size > MAX_MEMBER_BYTES
        || createHash("sha256").update(contents).digest("hex") !== member.sha256) {
      throw new Error(`Decoded Chromatic member differs from its original pin: ${name}`);
    }
    members.set(name, copy ? Buffer.from(contents) : contents);
    offset += member.size;
  }
  if (offset !== decoded.buffer.length) throw new Error("Unexpected decoded Chromatic bytes.");
  return members;
}

export function decodeChromaticExecutables(bytes, format = CHROMATIC_PACKED.format) {
  const pack = executablePack(format);
  return decodePack(bytes, pack, pack.targets.map((target) => [target, CHROMATIC_MEMBERS[CHROMATIC_TARGETS[target]]]));
}

export function decodeChromaticNotices(bytes) {
  return decodePack(bytes, CHROMATIC_NOTICE_PACK, Object.keys(CHROMATIC_TARGETS)
    .map((target) => [target, CHROMATIC_MEMBERS[`${target}/THIRD_PARTY_NOTICES.txt`]]), true);
}

export function decodeDeviceArtwork(bytes) {
  return decodePack(bytes, CHROMATIC_ARTWORK_PACK, Object.entries(CHROMATIC_ARTWORK_MEMBERS), true);
}

function readBounded(fd, maximum) {
  const bytes = Buffer.alloc(maximum + 1);
  let length = 0;
  while (length < bytes.length) {
    const count = readSync(fd, bytes, length, bytes.length - length, null);
    if (count === 0) break;
    length += count;
  }
  return bytes.subarray(0, length);
}

function unlinked(filename) {
  const absolute = path.resolve(filename);
  let current = path.parse(absolute).root;
  for (const part of absolute.slice(current.length).split(path.sep).filter(Boolean)) {
    current = path.join(current, part);
    if (lstatSync(current).isSymbolicLink() || realpathSync(current) !== current) throw new Error(`Chromatic runtime path is redirected: ${current}`);
  }
  return absolute;
}

function readStorageFile(filename, maximum, pin) {
  unlinked(filename);
  const before = lstatSync(filename);
  if (!before.isFile() || before.nlink !== 1 || before.size > maximum
      || (typeof process.getuid === "function" && before.uid !== process.getuid())
      || (process.platform !== "win32" && (before.mode & 0o022))
      || (pin && (before.size !== pin.size || chromaticDiskMode(before.mode) !== pin.mode))) {
    throw new Error(`Unsafe or changed Chromatic storage file: ${filename}`);
  }
  const fd = openSync(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
  try {
    if (!same(before, fstatSync(fd))) throw new Error("Chromatic storage changed while opening.");
    const bytes = readBounded(fd, maximum);
    unlinked(filename);
    if (bytes.length !== before.size || !same(before, fstatSync(fd)) || !same(before, lstatSync(filename))
        || (pin && createHash("sha256").update(bytes).digest("hex") !== pin.sha256)) {
      throw new Error(`Chromatic storage changed or differs from its pin: ${filename}`);
    }
    return bytes;
  } finally { closeSync(fd); }
}

/** Passive storage selection; unlike executable resolution, no host gate or cache. */
export function readChromaticPackageFormat(root = packageRoot) {
  const manifest = JSON.parse(readStorageFile(path.join(root, "package.json"), MAX_MANIFEST_BYTES).toString("utf8"));
  if (manifest.bundledChromatic !== CHROMATIC_VERSION) throw new Error("The package does not declare the bundled Chromatic release.");
  return chromaticFormatFromManifest(manifest);
}

/** Return the complete original notice for an explicit target on any host. */
export function readChromaticNotices(target, { root = packageRoot } = {}) {
  validatedTarget(target);
  const format = readChromaticPackageFormat(root);
  if (format === CHROMATIC_PACKED_V2.format) {
    return decodeChromaticNotices(readStorageFile(path.join(root, CHROMATIC_ROOT, CHROMATIC_NOTICE_PACK.member),
      CHROMATIC_NOTICE_PACK.size, CHROMATIC_NOTICE_PACK)).get(target);
  }
  const name = `${target}/THIRD_PARTY_NOTICES.txt`, pin = CHROMATIC_MEMBERS[name];
  return readStorageFile(path.join(root, CHROMATIC_ROOT, name), pin.size, pin);
}

/** Call only for a declared packed-artwork package. Missing/corrupt packs fail. */
export function readPackedDeviceArtwork(directory) {
  return decodeDeviceArtwork(readStorageFile(path.join(directory, CHROMATIC_ARTWORK_PACK.member),
    CHROMATIC_ARTWORK_PACK.size, CHROMATIC_ARTWORK_PACK));
}

/** Also used by packaging on other hosts; never executes an incompatible binary. */
function inspectChromaticBundle(root, { target, format } = {}, materializePacked = false) {
  const members = new Set(selectedMemberNames(target, format));
  const base = unlinked(path.join(root, CHROMATIC_ROOT));
  const directories = new Set([""]);
  for (const name of members) {
    const parts = name.split("/");
    for (let i = 1; i < parts.length; i++) directories.add(parts.slice(0, i).join("/"));
  }
  const found = [];
  let decoded, notices;
  function visit(relative) {
    const filename = unlinked(path.join(base, ...relative.split("/")));
    const before = lstatSync(filename);
    // Plugin installers may recreate source directories with mode 0775. Only
    // packed input may be read from those directories: every byte is pinned,
    // captured in memory, and materialized into the private executable cache.
    // Never execute a file from a writable source directory or relax file modes.
    const writableSourceDirectory = materializePacked && format !== undefined
      && directories.has(relative) && before.isDirectory();
    const forbiddenWriteBits = writableSourceDirectory ? 0o002 : 0o022;
    if ((typeof process.getuid === "function" && before.uid !== process.getuid()) ||
        (process.platform !== "win32" && (before.mode & forbiddenWriteBits))) throw new Error(
          `Unsafe Chromatic runtime ownership or permissions: ${filename} (mode ${(before.mode & 0o7777).toString(8)}, uid ${before.uid}, gid ${before.gid}; expected current-user ownership${typeof process.getuid === "function" ? ` uid ${process.getuid()}` : ""} and no group/other write permission)`);
    if (directories.has(relative)) {
      if (!before.isDirectory()) throw new Error(`Chromatic directory changed type: ${relative}`);
      const entries = readdirSync(filename);
      if (entries.length > members.size) throw new Error(`Unexpected Chromatic runtime entries: ${relative}`);
      for (const name of entries.sort()) visit(relative ? `${relative}/${name}` : name);
    } else {
      const member = physicalMember(relative, format);
      if (!members.has(relative) || !member || !before.isFile() || before.nlink !== 1 || before.size !== member.size || before.size > MAX_MEMBER_BYTES) throw new Error(`Unexpected Chromatic runtime member or size: ${relative}`);
      if (!allowedModes(relative, member, process.platform).includes(chromaticDiskMode(before.mode))) throw new Error(`Chromatic runtime member has an unexpected mode: ${relative}`);
      // A writable source directory could swap a regular file for a FIFO
      // between lstat and open. Do not block before the identity recheck.
      const fd = openSync(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
      try {
        const opened = fstatSync(fd);
        if (!same(before, opened)) throw new Error(`Chromatic runtime changed while opening: ${relative}`);
        const bytes = readBounded(fd, member.size);
        if (bytes.length !== before.size || createHash("sha256").update(bytes).digest("hex") !== member.sha256) throw new Error(`Chromatic runtime checksum mismatch: ${relative}`);
        if (!same(opened, fstatSync(fd))) throw new Error(`Chromatic runtime changed while reading: ${relative}`);
        if (format !== undefined && relative === executablePack(format).member) decoded = decodeChromaticExecutables(bytes, format);
        if (format === CHROMATIC_PACKED_V2.format && relative === CHROMATIC_NOTICE_PACK.member) notices = decodeChromaticNotices(bytes);
        found.push(relative);
      } finally { closeSync(fd); }
    }
    unlinked(filename);
    if (!same(before, lstatSync(filename))) throw new Error(`Chromatic runtime changed during verification: ${relative}`);
  }
  visit("");
  if (found.length !== members.size) throw new Error("Chromatic runtime is missing a pinned file.");
  if (format === CHROMATIC_PACKED_V2.format) readPackedDeviceArtwork(path.join(root, "assets", "devices"));
  return { version: CHROMATIC_VERSION, files: found, decoded, notices };
}

/** Passive authentication: decoding never writes into a package or cache. */
export function verifyChromaticBundle(root = packageRoot, options = {}) {
  const { decoded: _decoded, notices: _notices, ...result } = inspectChromaticBundle(root, options);
  return result;
}

const CACHE_MARKER = Buffer.from('{"schemaVersion":1,"owner":"modretro-chromatic","purpose":"verified-chromatic-executables"}' + String.fromCharCode(10));
function maybeStat(filename) {
  try { return lstatSync(filename); }
  catch (error) { if (error.code === "ENOENT") return undefined; throw error; }
}
function ownedDirectory(filename, privateMode = false) {
  unlinked(filename);
  const info = lstatSync(filename);
  if (!info.isDirectory() || (typeof process.getuid === "function" && info.uid !== process.getuid())
      || (process.platform !== "win32" && ((info.mode & 0o022) !== 0 || (privateMode && (info.mode & 0o777) !== 0o700)))) {
    throw new Error("Unsafe Chromatic cache directory: " + filename);
  }
  return info;
}
function ensureOwnedDirectory(filename, privateMode = true) {
  let created = false;
  if (!maybeStat(filename)) {
    const parent = path.dirname(filename);
    if (parent === filename) throw new Error("No owned parent for the Chromatic cache.");
    ensureOwnedDirectory(parent, false);
    try { mkdirSync(filename, { mode: 0o700 }); created = true; }
    catch (error) { if (error.code !== "EEXIST") throw error; }
  }
  return { identity: ownedDirectory(filename, privateMode), created };
}
function assertDirectoryIdentity(filename, before) {
  const after = ownedDirectory(filename, true);
  if (!["dev", "ino", "uid", "gid", "mode"].every((key) => before[key] === after[key])) {
    throw new Error("Chromatic cache directory identity changed.");
  }
}
function readCacheFile(filename, size, sha256, mode) {
  unlinked(filename);
  const before = lstatSync(filename);
  if (!before.isFile() || before.nlink !== 1 || before.size !== size || size > MAX_MEMBER_BYTES
      || (typeof process.getuid === "function" && before.uid !== process.getuid())
      || (process.platform !== "win32" && (before.mode & 0o777) !== mode)) {
    throw new Error("Unsafe or partial Chromatic cache file: " + filename);
  }
  const fd = openSync(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
  try {
    if (!same(before, fstatSync(fd))) throw new Error("Chromatic cache file changed while opening.");
    const bytes = readBounded(fd, size);
    if (bytes.length !== size || createHash("sha256").update(bytes).digest("hex") !== sha256
        || !same(before, fstatSync(fd)) || !same(before, lstatSync(filename))) {
      throw new Error("Chromatic cache file failed verification: " + filename);
    }
    unlinked(filename);
    return before;
  } finally { closeSync(fd); }
}

/** Materialize only for an actual vendor invocation, outside immutable inputs.
 * A corrupt existing cache entry is a refusal, never an overwrite or fallback. */
export function materializeChromaticExecutable(target, bytes, {
  cacheRoot = path.join(os.homedir(), ".modretro-chromatic-runtime"),
  notices,
} = {}) {
  validatedTarget(target);
  const member = CHROMATIC_MEMBERS[CHROMATIC_TARGETS[target]];
  if (!Buffer.isBuffer(bytes) || bytes.length !== member.size
      || createHash("sha256").update(bytes).digest("hex") !== member.sha256) {
    throw new Error("Cannot materialize an unverified Chromatic executable.");
  }
  const noticePin = CHROMATIC_MEMBERS[`${target}/THIRD_PARTY_NOTICES.txt`];
  if (notices !== undefined && (!Buffer.isBuffer(notices) || notices.length !== noticePin.size
      || createHash("sha256").update(notices).digest("hex") !== noticePin.sha256)) {
    throw new Error("Cannot materialize unverified Chromatic notices.");
  }
  const base = path.resolve(cacheRoot);
  const { identity: baseIdentity, created } = ensureOwnedDirectory(base);
  const marker = path.join(base, ".owner.json");
  if (created) {
    let fd;
    try {
      fd = openSync(marker, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600);
      writeFileSync(fd, CACHE_MARKER);
    } catch (error) { if (error.code !== "EEXIST") throw error; }
    finally { if (fd !== undefined) closeSync(fd); }
  }
  readCacheFile(marker, CACHE_MARKER.length, createHash("sha256").update(CACHE_MARKER).digest("hex"), 0o600);
  const bundle = path.join(base, notices === undefined ? CHROMATIC_PACKED.sha256 : CHROMATIC_PACKED_V2.sha256);
  const { identity: bundleIdentity } = ensureOwnedDirectory(bundle);
  const directory = path.join(bundle, target + "-" + member.sha256);
  const { identity: directoryIdentity } = ensureOwnedDirectory(directory);
  const executable = path.join(directory, path.basename(CHROMATIC_TARGETS[target]));
  // Make the target notice readable before publishing its executable. Both
  // files use the same no-overwrite, identity-checked promotion path.
  const files = [...(notices === undefined ? [] : [{ filename: path.join(directory, "THIRD_PARTY_NOTICES.txt"), bytes: notices, pin: noticePin }]),
    { filename: executable, bytes, pin: member }];
  for (const file of files) {
    if (!maybeStat(file.filename)) {
      const staging = mkdtempSync(path.join(directory, ".stage-"));
      const stagingIdentity = ownedDirectory(staging, true);
      const temporary = path.join(staging, path.basename(file.filename));
      let temporaryIdentity;
      try {
        const fd = openSync(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600);
        try {
          temporaryIdentity = fstatSync(fd);
          writeFileSync(fd, file.bytes);
          fchmodSync(fd, file.pin.mode);
        } finally { closeSync(fd); }
        readCacheFile(temporary, file.pin.size, file.pin.sha256, file.pin.mode);
        assertDirectoryIdentity(directory, directoryIdentity);
        try { linkSync(temporary, file.filename); }
        catch (error) { if (error.code !== "EEXIST") throw error; }
      } finally {
        assertDirectoryIdentity(staging, stagingIdentity);
        if (temporaryIdentity) {
          const current = lstatSync(temporary);
          if (current.dev !== temporaryIdentity.dev || current.ino !== temporaryIdentity.ino || current.uid !== temporaryIdentity.uid) {
            throw new Error("Chromatic staging identity changed; refusing cleanup.");
          }
          unlinkSync(temporary);
        }
        rmdirSync(staging);
      }
    }
    // The winning entry (ours or a concurrent producer's) must independently pass.
    readCacheFile(file.filename, file.pin.size, file.pin.sha256, file.pin.mode);
  }
  assertDirectoryIdentity(directory, directoryIdentity);
  assertDirectoryIdentity(bundle, bundleIdentity);
  assertDirectoryIdentity(base, baseIdentity);
  return executable;
}

export function resolveChromaticRuntime(options = {}) {
  if ("target" in options) throw new Error("Chromatic runtime selection comes from package.json; a caller target override is not permitted.");
  const { root = packageRoot, ...targetOptions } = options;
  // Preserve host/libc refusal before any package or native-file access.
  const hostTarget = selectChromaticTarget(targetOptions);
  const filename = unlinked(path.join(root, "package.json"));
  const before = lstatSync(filename);
  if (!before.isFile() || before.nlink !== 1 || before.size <= 0 || before.size > MAX_MANIFEST_BYTES ||
      (typeof process.getuid === "function" && before.uid !== process.getuid()) ||
      (process.platform !== "win32" && (before.mode & 0o022))) {
    throw new Error("Unsafe Chromatic package manifest type, size, ownership or permissions.");
  }
  const fd = openSync(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
  try {
    const unchanged = () => {
      unlinked(filename);
      if (!same(before, fstatSync(fd)) || !same(before, lstatSync(filename))) {
        throw new Error("The Chromatic package manifest changed during runtime resolution.");
      }
    };
    unchanged();
    const bytes = readFileSync(fd);
    if (bytes.length !== before.size) throw new Error("The Chromatic package manifest changed while reading.");
    unchanged();
    const manifest = JSON.parse(bytes.toString("utf8"));
    const target = chromaticTargetFromManifest(manifest);
    const format = chromaticFormatFromManifest(manifest);
    if (manifest.bundledChromatic !== CHROMATIC_VERSION) {
      throw new Error(`The package must declare bundledChromatic ${CHROMATIC_VERSION}.`);
    }
    requireChromaticHostTarget(target, targetOptions);
    const { decoded, notices, ...result } = inspectChromaticBundle(root, { target, format }, format !== undefined);
    unchanged();
    const executable = decoded === undefined ? path.join(root, CHROMATIC_ROOT, CHROMATIC_TARGETS[hostTarget])
      : materializeChromaticExecutable(hostTarget, decoded.get(hostTarget), { notices: notices?.get(hostTarget) });
    accessSync(executable, constants.X_OK);
    unchanged();
    return { ...result, platform: hostTarget, executable };
  } finally { closeSync(fd); }
}

// Offline notice access is deliberately separate from the vendor CLI. It does
// not select a host executable, create a cache or contact a device.
if (process.argv[1] && pathToFileURL(path.resolve(process.argv[1])).href === import.meta.url) {
  try {
    if (process.argv.length !== 4 || process.argv[2] !== "--notices") {
      throw new Error(`Usage: node scripts/chromatic-runtime.mjs --notices <${Object.keys(CHROMATIC_TARGETS).join("|")}>`);
    }
    process.stdout.write(readChromaticNotices(process.argv[3]));
  } catch (error) {
    console.error(error.message);
    process.exitCode = 1;
  }
}

SHA-256: 6c11b303e2db8a5ab49b68e01ffa9730db48437c14ec096c8f97afab8664d30b