#!/usr/bin/env node import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; import { constants, lstatSync, realpathSync } from "node:fs"; import { lstat, mkdir, open, readFile, realpath } from "node:fs/promises"; import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { ThtRunner } from "../dist/tht/tht-runner.js"; const modulePath = fileURLToPath(import.meta.url); const defaultRepositoryRoot = realpathSync(resolve(dirname(modulePath), "../..")); const HEX40 = /^[0-9a-f]{40}$/; const HEX64 = /^[0-9a-f]{64}$/; function fixedRoot(repositoryRoot) { return join(realpathSync(repositoryRoot), ".artifacts", "manual-acceptance", "p11"); } function below(parent, child) { const rel = relative(parent, child); return rel !== "" && !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel); } function assertNoSymlinks(root, path, allowMissingLeaf = false) { const rel = relative(root, path); if (rel.startsWith("..") || isAbsolute(rel)) throw new Error("path is outside owned root"); let cursor = root; const parts = rel.split(sep).filter(Boolean); for (const [index, part] of parts.entries()) { cursor = join(cursor, part); try { if (lstatSync(cursor).isSymbolicLink()) throw new Error("owned path contains a symlink"); } catch (error) { if (allowMissingLeaf && error?.code === "ENOENT" && index === parts.length - 1) return; throw error; } } } async function ownership(repositoryRoot, ownershipPath) { const root = fixedRoot(repositoryRoot); const expected = join(root, "ownership.json"); if (resolve(ownershipPath) !== expected) throw new Error("ownership path is not owned"); const rootEntry = await lstat(root); const ownershipEntry = await lstat(expected); if (!rootEntry.isDirectory() || rootEntry.isSymbolicLink() || !ownershipEntry.isFile() || ownershipEntry.isSymbolicLink()) throw new Error("ownership is unsafe"); if (await realpath(root) !== root) throw new Error("ownership root is not canonical"); let value; try { value = JSON.parse(await readFile(expected, "utf8")); } catch { throw new Error("ownership is malformed"); } if (value?.schemaVersion !== 1 || value.kind !== "p11-manual-acceptance" || !HEX64.test(value.nonce ?? "") || value.root !== root || value.repositoryRoot !== realpathSync(repositoryRoot)) { throw new Error("ownership identity mismatch"); } return { root, value }; } const ANCHORED_PUBLISH_SOURCE=String.raw`import os,secrets,stat,sys parent,name,expected_dev,expected_ino=sys.argv[1:] pfd=fd=None;stage=".render-stage-"+secrets.token_hex(16);published=False def fail(): raise RuntimeError("anchored publication refused") try: pfd=os.open(parent,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW) identity=os.fstat(pfd) if (identity.st_dev,identity.st_ino)!=(int(expected_dev),int(expected_ino)): fail() try: os.stat(name,dir_fd=pfd,follow_symlinks=False); fail() except FileNotFoundError: pass fd=os.open(stage,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600,dir_fd=pfd) data=sys.stdin.buffer.read(33554433) if len(data)>33554432: fail() view=memoryview(data) while view: written=os.write(fd,view) if written<=0: fail() view=view[written:] os.fsync(fd);os.close(fd);fd=None;os.rename(stage,name,src_dir_fd=pfd,dst_dir_fd=pfd);published=True;os.fsync(pfd) current=os.stat(parent,follow_symlinks=False) if not stat.S_ISDIR(current.st_mode) or (current.st_dev,current.st_ino)!=(identity.st_dev,identity.st_ino): fail() except Exception: if published: try: os.unlink(name,dir_fd=pfd);os.fsync(pfd) except Exception: pass print("anchored output publication refused (details redacted)",file=sys.stderr);raise SystemExit(1) finally: if fd is not None: os.close(fd) if pfd is not None: try: os.unlink(stage,dir_fd=pfd) except FileNotFoundError: pass os.close(pfd) `; async function atomicCopy(source, output) { const parent = dirname(output); const entry = await lstat(parent); if (!entry.isDirectory() || entry.isSymbolicLink()) throw new Error("rendered parent identity is unsafe"); const bytes = await readFile(source); const result = spawnSync("python3", ["-c", ANCHORED_PUBLISH_SOURCE, parent, basename(output), String(entry.dev), String(entry.ino)], { input: bytes, encoding: "utf8", maxBuffer: 1024 * 1024 }); if (result.error || result.status !== 0) throw new Error("anchored output publication refused; rendered parent identity changed or output is unsafe"); } function sameEntry(actual, expected) { return actual.dev === expected.dev && actual.ino === expected.ino; } async function readBounded(path, max, label) { let handle; try { handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW); const before = await handle.stat(); const pathEntry = await lstat(path); if (!before.isFile() || pathEntry.isSymbolicLink() || !pathEntry.isFile() || !sameEntry(before, pathEntry)) throw new Error(`${label} is unsafe`); if (before.size < 1 || before.size > max) throw new Error(`${label} is unbounded`); const bytes = Buffer.alloc(before.size); let offset = 0; while (offset < bytes.length) { const { bytesRead } = await handle.read(bytes, offset, bytes.length - offset, offset); if (bytesRead < 1) throw new Error(`${label} changed while reading`); offset += bytesRead; } const after = await handle.stat(); if (!sameEntry(before, after) || after.size !== before.size) throw new Error(`${label} changed while reading`); return bytes; } finally { if (handle) await handle.close().catch(() => {}); } } async function readSnapshotManifest(root, manifestPath, commit, yamlName, expectedDigest) { let manifestEntry; try { assertNoSymlinks(root, manifestPath); manifestEntry = await lstat(manifestPath); } catch (error) { if (error?.code === "ENOENT") throw new Error("snapshot manifest is missing or unbounded"); throw error; } if (!manifestEntry.isFile() || manifestEntry.isSymbolicLink() || await realpath(manifestPath) !== manifestPath) throw new Error("snapshot manifest is unsafe"); const bytes = await readBounded(manifestPath, 1024 * 1024, "snapshot manifest"); let manifest; try { manifest = JSON.parse(bytes.toString("utf8")); } catch { throw new Error("snapshot manifest is malformed"); } const files = manifest?.files; if (manifest?.head !== commit || !files || typeof files !== "object" || Array.isArray(files)) throw new Error("snapshot manifest identity is unsafe"); if (!HEX64.test(files[yamlName] ?? "") || files[yamlName] !== expectedDigest) throw new Error("snapshot manifest digest is unsafe"); return manifest; } export async function renderOwnedSnapshot({ repositoryRoot = defaultRepositoryRoot, ownershipPath, snapshotPath, outputPath, snapshotSha256, env = process.env, beforePublish }) { const repo = realpathSync(repositoryRoot); const { root } = await ownership(repo, resolve(repo, ownershipPath)); const snapshot = resolve(repo, snapshotPath); const output = resolve(repo, outputPath); const snapshotsRoot = join(root, "installation", "registry", "snapshots"); const renderedRoot = join(root, "rendered"); if (!isAbsolute(snapshotPath) || !below(snapshotsRoot, snapshot)) throw new Error("snapshot is not an owned absolute path"); const match = /^([0-9a-f]{40})\/([a-z][a-z0-9-]{2,62})\.yaml$/.exec(relative(snapshotsRoot, snapshot).split(sep).join("/")); if (!match || !HEX40.test(match[1])) throw new Error("snapshot is not commit addressed"); if (!HEX64.test(snapshotSha256 ?? "")) throw new Error("snapshot digest identity is unsafe"); assertNoSymlinks(root, snapshot); const snapshotEntry = await lstat(snapshot); if (!snapshotEntry.isFile() || snapshotEntry.isSymbolicLink() || await realpath(snapshot) !== snapshot) throw new Error("snapshot is unsafe"); const yamlName = `${match[2]}.yaml`; await readSnapshotManifest(root, join(snapshotsRoot, match[1], "snapshot.json"), match[1], yamlName, snapshotSha256); const snapshotBytes = await readBounded(snapshot, 1024 * 1024, "snapshot"); if (createHash("sha256").update(snapshotBytes).digest("hex") !== snapshotSha256) throw new Error("snapshot bytes changed"); if (!below(renderedRoot, output) || dirname(output) !== renderedRoot || !output.endsWith(".yaml")) throw new Error("output is not an owned rendered path"); assertNoSymlinks(root, dirname(output)); try { if ((await lstat(output)).isSymbolicLink()) throw new Error("output is unsafe"); } catch (error) { if (error.code !== "ENOENT") throw error; } await mkdir(join(snapshotsRoot, "runtime"), { recursive: true, mode: 0o700 }); const bindingEnv = Object.fromEntries((await readFile(join(root, "installation", "bindings.env"), "utf8")).trim().split(/\n+/).filter(Boolean).map((line) => line.split(/=(.+)/))); const effectiveEnv = { ...bindingEnv, ...env }; const prior = {}; for (const [key, value] of Object.entries(effectiveEnv)) { prior[key] = process.env[key]; if (value === undefined) delete process.env[key]; else process.env[key] = value; } const runner = new ThtRunner({ thtBin: join(repo, "harness", ".venv", "bin", "tht"), harnessDir: join(repo, "harness"), configPath: join(root, "installation", "runtime", "base.yaml"), dataRoot: join(root, "installation", "data"), runtimeSnapshotRoot: join(snapshotsRoot, "runtime"), secretRoots: [join(root, "fixture-secrets")], semanticRuntime: { internalQdrantUrl: "http://qdrant:6333", internalEmbeddingUrl: "http://embedding:11434", internalEmbeddingModel: "qwen3-embedding:0.6b", internalEmbeddingDimensions: 1024 }, }); let lease; try { lease = runner.acquireWorkspaceRuntime(snapshot); const verifySnapshot = async () => { const current = await readBounded(snapshot, 1024 * 1024, "snapshot"); if (createHash("sha256").update(current).digest("hex") !== snapshotSha256) throw new Error("snapshot content changed during rendering"); }; await verifySnapshot(); if (beforePublish) await beforePublish({ output, renderedRoot }); await verifySnapshot(); await atomicCopy(lease.path, output); } finally { if (lease) lease.release(); for (const key of Object.keys(env)) { if (prior[key] === undefined) delete process.env[key]; else process.env[key] = prior[key]; } } return output; } function parseArgs(argv) { if (argv.length !== 8) throw new Error("usage: p11-render-snapshot.mjs --ownership PATH --snapshot ABSOLUTE_PATH --output PATH --snapshot-sha256 HEX"); const result = {}; for (let index = 0; index < argv.length; index += 2) { if (!["--ownership", "--snapshot", "--output", "--snapshot-sha256"].includes(argv[index]) || result[argv[index]]) throw new Error("invalid arguments"); result[argv[index]] = argv[index + 1]; } return result; } if (process.argv[1] && realpathSync(process.argv[1]) === modulePath) { try { const args = parseArgs(process.argv.slice(2)); await renderOwnedSnapshot({ ownershipPath: args["--ownership"], snapshotPath: args["--snapshot"], outputPath: args["--output"], snapshotSha256: args["--snapshot-sha256"] }); console.log(`rendered ${resolve(args["--output"])}`); } catch (error) { console.error(`p11 render refused: ${error.message}`); process.exitCode = 1; } }