QRun-IO/ci-policy: ci / fork-guard (push) Skipped
QRun-IO/ci-policy: ci / head-profile (push) Skipped
QRun-IO/ci-policy: ci / application-template-0 (push) Skipped
QRun-IO/ci-policy: ci / gradle-1 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (push) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (push) Skipped
QRun-IO/ci-policy: ci / node-8 (push) Skipped
QRun-IO/ci-policy: ci / node-9 (push) Skipped
QRun-IO/ci-policy: ci / node-10 (push) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (push) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (push) Skipped
QRun-IO/ci-policy: ci / source-config-13 (push) Skipped
QRun-IO/ci-policy: ci / source-config-14 (push) Skipped
QRun-IO/ci-policy: ci / android-0 (push) Skipped
QRun-IO/ci-policy: ci / original-business (push) Skipped
QRun-IO/ci-policy: ci / original-mcp (push) Skipped
QRun-IO/ci-policy: ci / original-voyage (push) Skipped
QRun-IO/ci-policy: ci / original-cli (push) Skipped
QRun-IO/ci-policy: ci / repository-policy (push) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (push) Skipped
QRun-IO/ci-policy: ci / not-enrolled (push) Failing after 7s
QRun-IO/ci-policy: native / fork-deny (push) Skipped
QRun-IO/ci-policy: native / dotnet-0 (push) Skipped
QRun-IO/ci-policy: ci / ci-result (push) Failing after 6s
QRun-IO/ci-policy: native / native-result (push) Successful in 6s
Save the current implementation and README, status, and known-issue documentation at the user-requested stop. No completed release or deployment is claimed. Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: GPT-6 Codex <noreply@openai.com>
54 lines
3.4 KiB
JavaScript
54 lines
3.4 KiB
JavaScript
// Copyright (C) 2026 Kingsrook, LLC.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
import { createHash } from "node:crypto";
|
|
import { copyFile, lstat, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
import path from "node:path";
|
|
|
|
// Packaging only. Never imports the compiler, executes source or installs packages.
|
|
// Root runs this with the approved exact Node executable after worker npm run build.
|
|
if (process.versions.node !== "24.22.2" || process.argv.length !== 4) {
|
|
throw new Error("Use Node 24.22.2: build-compiler-image.mjs <absolute-worker-root> <new-absolute-output-root>");
|
|
}
|
|
const worker = process.argv[2];
|
|
const output = process.argv[3];
|
|
if (!path.isAbsolute(worker) || !path.isAbsolute(output) || output.includes("*") || output.includes(",")) {
|
|
throw new Error("Absolute literal paths required");
|
|
}
|
|
const tsPackage = JSON.parse(await readFile(path.join(worker, "node_modules/typescript/package.json"), "utf8"));
|
|
if (tsPackage.version !== "6.0.3") throw new Error("TypeScript 6.0.3 required");
|
|
const libs = (await readdir(path.join(worker, "node_modules/typescript/lib")))
|
|
.filter(name => /^lib\.[a-z0-9.]+\.d\.ts$/.test(name))
|
|
.map(name => "node_modules/typescript/lib/" + name);
|
|
const files = ["package.json", "dist/compiler-entry.js", "dist/compiler.js", "dist/frames.js", "dist/protocol.js",
|
|
"node_modules/typescript/package.json", "node_modules/typescript/lib/typescript.js", ...libs].sort();
|
|
if (files.length > 256 || libs.length === 0) throw new Error("Compiler closure size");
|
|
await mkdir(output); // Deliberately refuses any existing output; never overwrites a sealed image.
|
|
const root = path.join(output, "compiler");
|
|
await mkdir(root);
|
|
let total = 0;
|
|
const hashes = {};
|
|
for (const name of files) {
|
|
const source = path.join(worker, name);
|
|
const stat = await lstat(source);
|
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size < 1 || stat.size > 16 * 1024 * 1024) throw new Error("Invalid compiler source file");
|
|
total += stat.size;
|
|
if (total > 64 * 1024 * 1024) throw new Error("Compiler closure bytes");
|
|
const content = await readFile(source);
|
|
hashes[name] = createHash("sha256").update(content).digest("hex");
|
|
const target = path.join(root, name);
|
|
await mkdir(path.dirname(target), { recursive: true });
|
|
await writeFile(target, content, { flag: "wx" });
|
|
}
|
|
const manifest = JSON.stringify({ protocol: "qqq-typescript-image/1", nodeVersion: "24.22.2", typescriptVersion: "6.0.3", files: hashes }, null, 2) + "\n";
|
|
await writeFile(path.join(root, "compiler-manifest.json"), manifest, { flag: "wx" });
|
|
// Notices are adjacent to, never extra executable files inside, the closed tree.
|
|
const notices = path.join(output, "notices");
|
|
await mkdir(notices);
|
|
await copyFile(path.join(worker, "node_modules/typescript/LICENSE.txt"), path.join(notices, "typescript-LICENSE.txt"));
|
|
await copyFile(path.join(worker, "LICENSE"), path.join(notices, "worker-LICENSE"));
|
|
await copyFile(path.join(worker, "NOTICE"), path.join(notices, "worker-NOTICE"));
|
|
const nodeHash = createHash("sha256").update(await readFile(process.execPath)).digest("hex");
|
|
const evidence = { nodePath: process.execPath, nodeSha256: nodeHash, compilerRoot: root,
|
|
manifestSha256: createHash("sha256").update(manifest).digest("hex"), files: files.length, bytes: total };
|
|
await writeFile(path.join(output, "compiler-image.json"), JSON.stringify(evidence, null, 2) + "\n", { flag: "wx" });
|
|
console.log(JSON.stringify(evidence)); |