#!/usr/bin/env node import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import process from "node:process"; function fail(message) { console.error(message); process.exit(1); } function walk(directory, prefix = "") { const files = []; for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { if (!prefix && entry.name === ".git") continue; const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name; const absolutePath = path.join(directory, entry.name); if (entry.isSymbolicLink()) fail(`Symbolic link present in public export: ${relativePath}`); if (entry.isDirectory()) files.push(...walk(absolutePath, relativePath)); else if (entry.isFile()) files.push(relativePath); else fail(`Non-regular entry present in public export: ${relativePath}`); } return files; } const required = [ "README.md", "SECURITY.md", "CONTRIBUTING.md", "LICENSE", "VERSION", "PUBLIC_SOURCE_EXPORT.md", "PUBLIC_SOURCE_MANIFEST.json", "docker-compose.yml", "backend/pyproject.toml", "frontend/package.json", "node-agent/pyproject.toml", "runtime-worker/pyproject.toml" ]; const missing = required.filter((entry) => !fs.existsSync(path.join(process.cwd(), entry))); if (missing.length > 0) { fail(`Missing public source files: ${missing.join(", ")}`); } for (const privatePath of [".claude", ".agents", ".codex", "artifacts", "docs/quality"]) { if (fs.existsSync(path.join(process.cwd(), privatePath))) { fail(`Private-only path present in public export: ${privatePath}`); } } const manifest = JSON.parse(fs.readFileSync("PUBLIC_SOURCE_MANIFEST.json", "utf8")); if ( manifest.schemaVersion !== 1 || typeof manifest.sourceRevision !== "string" || !/^[0-9a-f]{40}$/u.test(manifest.sourceRevision) || !Array.isArray(manifest.files) || manifest.files.length === 0 ) { fail("PUBLIC_SOURCE_MANIFEST.json has an invalid schema or source revision."); } const declared = new Set(); for (const entry of manifest.files) { if ( !entry || typeof entry.path !== "string" || entry.path !== path.posix.normalize(entry.path) || path.posix.isAbsolute(entry.path) || entry.path.startsWith("../") || entry.path.includes("\\") || !Number.isSafeInteger(entry.bytes) || entry.bytes < 0 || typeof entry.sha256 !== "string" || !/^[0-9a-f]{64}$/u.test(entry.sha256) ) { fail("PUBLIC_SOURCE_MANIFEST.json contains an invalid file entry."); } const collisionKey = entry.path.toLocaleLowerCase("en-US"); if (declared.has(collisionKey)) fail(`Duplicate manifest path: ${entry.path}`); declared.add(collisionKey); const absolutePath = path.join(process.cwd(), ...entry.path.split("/")); if (!fs.existsSync(absolutePath)) fail(`Manifest file is missing: ${entry.path}`); const stat = fs.lstatSync(absolutePath); if (!stat.isFile() || stat.isSymbolicLink()) { fail(`Manifest path is not a regular file: ${entry.path}`); } const bytes = fs.readFileSync(absolutePath); const digest = crypto.createHash("sha256").update(bytes).digest("hex"); if (bytes.length !== entry.bytes) fail(`Manifest size mismatch: ${entry.path}`); if (digest !== entry.sha256) fail(`Manifest hash mismatch: ${entry.path}`); } const generated = new Set(["public_source_export.md", "public_source_manifest.json"]); const unexpected = walk(process.cwd()).filter( (entry) => !declared.has(entry.toLocaleLowerCase("en-US")) && !generated.has(entry.toLocaleLowerCase("en-US")) ); if (unexpected.length > 0) fail(`Unexpected public source files: ${unexpected.join(", ")}`); console.log(`Public source integrity passed (${manifest.files.length} allowlisted files).`);