openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
2,540 lines • 99 kB
JavaScript
import { Et as _enum, Fn as object, Jn as string, Lt as boolean, Nt as array, Pn as number, Yt as discriminatedUnion, lr as uuid, or as union, qn as strictObject, sr as unknown, xn as literal } from "./schemas-BOYIvvln.mjs";
import { i as runManagedCommand, n as hasUnjoinedWork } from "./managed-child-process-DzXLUTpR.mjs";
import { accessSync, chmodSync, closeSync, constants, fchmodSync, fstatSync, fsyncSync, lstatSync, mkdirSync, mkdtempSync, openSync, opendirSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, rmdirSync, statSync, writeFileSync, writeSync } from "node:fs";
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
import { spawnSync } from "node:child_process";
import { createHash, randomUUID } from "node:crypto";
import { performance } from "node:perf_hooks";
import { isUtf8 } from "node:buffer";
import { DatabaseSync } from "node:sqlite";
//#region scripts/crabbox-staging-witness.mts
const objectId = /^[0-9a-f]{40}$/u;
const sourceModes = /* @__PURE__ */ new Set([
"100644",
"100755",
"120000"
]);
const maxEntries$1 = 1e5;
const maxMetadataBytes = 67108864;
const maxSourceBytes = 8589934592;
const baseBudgetMs = 12e4;
const budgetPerGiBMs = 3e4;
const maxBudgetMs = 18e5;
function gitEnvironment() {
return {
...Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.toUpperCase().startsWith("GIT_"))),
GIT_OPTIONAL_LOCKS: "0",
GIT_NO_LAZY_FETCH: "1",
GIT_NO_REPLACE_OBJECTS: "1",
GIT_CONFIG_NOSYSTEM: "1",
GIT_CONFIG_GLOBAL: "/dev/null",
GIT_TERMINAL_PROMPT: "0"
};
}
const gitOptions = [
"--no-lazy-fetch",
"--no-replace-objects",
"-c",
"gc.auto=0",
"-c",
"maintenance.auto=false",
"-c",
"core.fsmonitor=false",
"-c",
"core.commitGraph=false",
"-c",
"core.multiPackIndex=false"
];
function workBudgetExceeded() {
return /* @__PURE__ */ new Error("source witness verification exceeded its work budget; retry later, repack the witness repository, or choose another --witness-repo/--witness-ref");
}
function remainingTime(deadline) {
const remaining = deadline - Date.now();
if (remaining <= 0) throw workBudgetExceeded();
return remaining;
}
function gitRead(location, args, deadline, options = {}) {
const result = spawnSync("git", [
...gitOptions,
...location,
...args
], {
env: gitEnvironment(),
stdio: [
"ignore",
options.quiet ? "ignore" : "pipe",
"pipe"
],
timeout: remainingTime(deadline),
killSignal: "SIGKILL",
maxBuffer: options.quiet ? 1048576 : maxMetadataBytes
});
if (!result.error && options.absent && result.status === 1) return;
if (result.error && "code" in result.error && result.error.code === "ETIMEDOUT") throw workBudgetExceeded();
if (result.error || result.status !== 0) {
const reason = !result.error && typeof result.status === "number" ? options.failure?.(result.status) : void 0;
throw new Error(reason ?? `source witness Git ${args[0]} could not verify local objects`);
}
return result.stdout ?? Buffer.alloc(0);
}
function gitText(location, args, deadline) {
const value = gitRead(location, args, deadline);
if (!isUtf8(value)) throw new Error("source witness Git metadata is not UTF-8");
return value.toString("utf8").trim();
}
function retainedRef(ref) {
return ref.startsWith("refs/") && ref.length <= 1024 && !ref.endsWith("/HEAD") && !ref.includes("\\") && !ref.includes("\0") && !ref.split("/").some((part) => !part || part === "." || part === "..") && ![
"refs/openclaw/source-capsule",
"refs/bisect/",
"refs/rewritten/",
"refs/worktree/",
"refs/replace/"
].some((prefix) => ref === prefix || ref.startsWith(prefix.endsWith("/") ? prefix : `${prefix}/`));
}
function resolveRef(location, ref, deadline) {
if (!retainedRef(ref)) throw new Error("source witness needs a named non-staging Git ref");
gitRead(location, ["check-ref-format", ref], deadline);
if (gitRead(location, [
"symbolic-ref",
"--quiet",
ref
], deadline, { absent: true })) throw new Error("source witness ref must name retained objects directly");
const oid = gitText(location, [
"rev-parse",
"--verify",
"--end-of-options",
ref
], deadline);
const commit = gitText(location, [
"rev-parse",
"--verify",
"--end-of-options",
`${ref}^{commit}`
], deadline);
if (!objectId.test(oid) || !objectId.test(commit)) throw new Error("source witness requires complete SHA-1 Git identities");
return {
oid,
commit
};
}
/** Capture only an existing branch or exact ref, without searching commit history. */
function captureSourceWitness(repoRoot, sourceSha) {
try {
if (!objectId.test(sourceSha)) return;
const deadline = Date.now() + 5e3;
const location = ["-C", repoRoot];
const gitDir = realpathSync(gitText(location, [
"rev-parse",
"--path-format=absolute",
"--git-common-dir"
], deadline));
const symbolic = gitRead(location, [
"symbolic-ref",
"--quiet",
"HEAD"
], deadline, { absent: true });
const refs = symbolic ? [symbolic.toString("utf8").trim()] : gitText(location, [
"for-each-ref",
"--count=32",
"--format=%(refname)",
"--points-at",
sourceSha,
"refs/heads",
"refs/remotes",
"refs/tags"
], deadline).split("\n");
for (const ref of refs.filter(retainedRef)) if (resolveRef(location, ref, deadline).commit === sourceSha) return {
gitDir,
ref,
commit: sourceSha
};
} catch {}
}
/** Select an operator-owned retained ref without creating refs or copying source. */
function selectSourceWitness(repository, ref) {
if (!retainedRef(ref)) throw new Error("Choose a full retained refs/heads, refs/remotes, or refs/tags name outside staging.");
const deadline = Date.now() + 5e3;
const location = ["-C", repository];
return {
gitDir: realpathSync(gitText(location, [
"rev-parse",
"--path-format=absolute",
"--git-common-dir"
], deadline)),
ref,
commit: resolveRef(location, ref, deadline).commit
};
}
function overlaps$2(left, right) {
const within = (parent, child) => {
const path = relative(parent, child);
return path === "" || !isAbsolute(path) && path !== ".." && !path.startsWith(`..${sep}`);
};
return within(left, right) || within(right, left);
}
function sourcePath(path) {
if (!path || path.includes("\0") || path.includes("\\") || Buffer.from(path).toString("utf8") !== path || path.split("/").some((part) => !part || part === "." || part === ".." || part.toLowerCase() === ".git")) throw new Error("source witness manifest has an invalid repository path");
return path;
}
function validateSource(source) {
if (source.files.length + source.deleted.length > maxEntries$1) throw new Error("source witness manifest exceeds its entry budget");
const files = /* @__PURE__ */ new Set();
const directories = /* @__PURE__ */ new Set();
for (const entry of source.files) {
const path = sourcePath(entry.path);
if (files.has(path) || !sourceModes.has(entry.mode) || !objectId.test(entry.blob)) throw new Error("source witness manifest has duplicate or invalid source entries");
files.add(path);
for (let slash = path.lastIndexOf("/"); slash >= 0; slash = path.lastIndexOf("/", slash - 1)) directories.add(path.slice(0, slash));
}
if ([...files].some((path) => directories.has(path))) throw new Error("source witness manifest has conflicting file and directory paths");
const deleted = /* @__PURE__ */ new Set();
for (const entry of source.deleted) {
const path = sourcePath(entry);
if (deleted.has(path) || files.has(path) || directories.has(path)) throw new Error("source witness manifest has conflicting deletions");
deleted.add(path);
}
}
/** First eligibility tier: an ordinary self-contained local object store. */
function storageIdentity(gitDir, payloadRoot, ref, deadline) {
const digest = createHash("sha256");
let count = 0;
let objectBytes = 0n;
const record = (path) => {
remainingTime(deadline);
const stat = lstatSync(path, {
bigint: true,
throwIfNoEntry: false
});
if (!stat) {
digest.update(`${path}\0missing\0`);
return;
}
if (stat.isSymbolicLink() || !stat.isDirectory() && !stat.isFile()) throw new Error("source witness Git storage contains a symbolic link or unsupported file kind");
if (++count > 25e4) throw new Error("source witness object storage exceeds its inspection budget");
digest.update(`${path}\0${stat.dev}:${stat.ino}:${stat.mode}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}\0`);
return stat;
};
if (realpathSync(gitDir) !== gitDir || overlaps$2(gitDir, payloadRoot) || !record(gitDir)?.isDirectory()) throw new Error("source witness Git repository overlaps the disposable payload");
for (const name of [
"HEAD",
"config",
"config.worktree",
"packed-refs",
"commondir",
"shallow",
"info/grafts",
ref
]) {
const parts = name.split("/");
for (let end = 1; end < parts.length; end += 1) {
const parent = record(join(gitDir, ...parts.slice(0, end)));
if (parent && !parent.isDirectory()) throw new Error("source witness Git metadata has an unsupported parent path");
}
const stat = record(join(gitDir, name));
if (stat && !stat.isFile()) throw new Error("source witness Git metadata is not a regular file");
if (stat && [
"commondir",
"shallow",
"info/grafts"
].includes(name) && stat.size > 0n) throw new Error("source witness needs complete local history without redirected or truncated storage");
}
const walk = (directory, depth) => {
if (depth > 4 || !record(directory)?.isDirectory()) throw new Error("source witness object storage has an unsupported directory layout");
for (const name of readdirSync(directory).toSorted()) {
const path = join(directory, name);
const stat = record(path);
if (!stat) throw new Error("source witness object storage changed during inspection");
if (name.endsWith(".promisor")) throw new Error("source witness has promised objects; choose an independent complete store");
if ((name === "alternates" || name === "http-alternates") && stat.size > 0n) throw new Error("source witness borrows objects; choose an independent complete store");
if (stat.isDirectory()) walk(path, depth + 1);
else if (stat.isFile()) objectBytes += stat.size > 4096n ? stat.size : 4096n;
}
};
walk(join(gitDir, "objects"), 0);
return {
identity: digest.digest("hex"),
objectBytes
};
}
async function verifyBlobs(location, blobs, deadline, signal) {
if (blobs.length === 0) return;
const abort = new AbortController();
let failure;
let header = "";
let index = 0;
let remaining = 0;
let bytes = 0;
let hash;
const consume = (chunk) => {
try {
for (let offset = 0; offset < chunk.length;) {
if (failure) return;
if (remaining > 0) {
const end = offset + Math.min(remaining, chunk.length - offset);
hash.update(chunk.subarray(offset, end));
remaining -= end - offset;
offset = end;
} else if (hash) {
if (chunk[offset++] !== 10 || hash.digest("hex") !== blobs[index]) throw new Error("source witness raw blob identity mismatch");
hash = void 0;
index += 1;
} else {
const value = chunk[offset++];
if (value !== 10) {
header += String.fromCharCode(value);
if (header.length > 128) throw new Error("source witness returned invalid object framing");
continue;
}
const match = /^([0-9a-f]{40}) blob (0|[1-9][0-9]*)$/u.exec(header);
if (!match || match[1] !== blobs[index]) throw new Error("source witness raw blob is missing or has the wrong type");
remaining = Number(match[2]);
bytes += remaining;
if (!Number.isSafeInteger(remaining) || bytes > maxSourceBytes) throw new Error("source witness raw blobs exceed the verification byte budget");
hash = createHash("sha1").update(`blob ${remaining}\0`);
header = "";
}
}
} catch (error) {
failure = error instanceof Error ? error : /* @__PURE__ */ new Error("source witness blob verification failed");
abort.abort(failure);
}
};
try {
if (await runManagedCommand({
bin: "git",
args: [
...gitOptions,
...location,
"cat-file",
"--batch"
],
env: gitEnvironment(),
stdio: [
"pipe",
"pipe",
"pipe"
],
timeoutMs: remainingTime(deadline),
signal: signal ? AbortSignal.any([signal, abort.signal]) : abort.signal,
requireProcessTreeExit: true,
onReady(child) {
child.stdout.on("data", consume);
child.stderr.resume();
child.stdin.on("error", () => {});
child.stdin.end(`${blobs.join("\n")}\n`);
}
}) !== 0 || failure || hash || header || index !== blobs.length) throw failure ?? /* @__PURE__ */ new Error("source witness did not supply every complete raw blob");
} catch (error) {
if (failure && failure !== error) throw new AggregateError([failure, error], failure.message, { cause: error });
throw error;
}
}
function fsckFailure(status) {
if (status < 128 && (status & 7) !== 0) return "source witness Git fsck found missing, corrupt, or unconnected objects; choose a complete --witness-repo/--witness-ref";
if (status === 8) return "source witness Git reference database has errors; repair its refs or choose another --witness-repo/--witness-ref";
}
function supportsNoReferences(location, deadline) {
const version = /^git version (\d+)\.(\d+)/u.exec(gitText(location, ["version"], deadline));
return version !== null && (Number(version[1]) > 2 || Number(version[1]) === 2 && Number(version[2]) >= 50);
}
/** Read-only proof of another retained copy; the stage owner still owns disposal. */
async function verifySourceWitness(params) {
try {
params.signal?.throwIfAborted();
validateSource(params.source);
const { ref: refName, commit } = params.witness;
if (!objectId.test(commit) || !retainedRef(refName)) throw new Error("source witness needs an exact commit and named non-staging ref");
const started = Date.now();
const payloadRoot = realpathSync(params.payloadRoot);
const gitDir = realpathSync(params.witness.gitDir);
const location = [`--git-dir=${gitDir}`];
const before = storageIdentity(gitDir, payloadRoot, refName, started + baseBudgetMs);
const deadline = started + (params.automatic ? baseBudgetMs : Math.min(maxBudgetMs, baseBudgetMs + Math.ceil(Number(before.objectBytes) / 1024 ** 3 * budgetPerGiBMs)));
if (gitRead(location, [
"config",
"--no-includes",
"--get-regexp",
"^(include\\.|includeif\\.|extensions\\.(partialclone|refstorage)|remote\\..*\\.promisor$|fsck\\.)"
], deadline, { absent: true })) throw new Error("source witness uses configuration that prevents independent local verification");
if (gitText(location, ["rev-parse", "--show-object-format"], deadline) !== "sha1") throw new Error("source witness requires a SHA-1 Git object store");
const ref = resolveRef(location, refName, deadline);
gitRead(location, [
"merge-base",
"--is-ancestor",
commit,
ref.commit
], deadline);
gitRead(location, [
"fsck",
"--connectivity-only",
"--no-dangling",
"--no-reflogs",
"--no-progress",
...supportsNoReferences(location, deadline) ? ["--no-references"] : [],
ref.oid
], deadline, {
quiet: true,
failure: fsckFailure
});
const listing = gitRead(location, [
"ls-tree",
"-r",
"-t",
"-z",
"--full-tree",
commit
], deadline);
if (!isUtf8(listing)) throw new Error("source witness tree paths are not UTF-8");
const entries = /* @__PURE__ */ new Map();
for (const row of listing.toString("utf8").split("\0").filter(Boolean)) {
const match = /^(040000 tree|100644 blob|100755 blob|120000 blob|160000 commit) ([0-9a-f]{40})\t([\s\S]+)$/u.exec(row);
if (!match || !match[1] || !match[2] || !match[3] || entries.has(match[3])) throw new Error("source witness tree has unsupported or duplicate entries");
entries.set(sourcePath(match[3]), {
mode: match[1].slice(0, 6),
blob: match[2]
});
}
for (const entry of params.source.files) {
const saved = entries.get(entry.path);
if (saved?.mode !== entry.mode || saved.blob !== entry.blob) throw new Error(`source witness does not preserve ${JSON.stringify(entry.path)}`);
}
for (const path of params.source.deleted) if (entries.has(path)) throw new Error(`source witness does not preserve deletion of ${JSON.stringify(path)}`);
await verifyBlobs(location, [...new Set(params.source.files.map((entry) => entry.blob))], deadline, params.signal);
const revalidate = () => {
params.signal?.throwIfAborted();
const revalidationDeadline = params.automatic ? deadline : Date.now() + baseBudgetMs;
const currentStorage = storageIdentity(gitDir, payloadRoot, refName, revalidationDeadline);
const after = resolveRef(location, refName, revalidationDeadline);
if (currentStorage.identity !== before.identity || after.oid !== ref.oid || after.commit !== ref.commit) throw new Error("source witness changed while preservation was being verified");
};
revalidate();
return {
ok: true,
witness: {
gitDir,
ref: refName,
commit
},
revalidate
};
} catch (error) {
return {
ok: false,
reason: error instanceof Error ? error.message : "source witness could not be verified",
error,
...hasUnjoinedWork(error) ? { unjoined: true } : {}
};
}
}
//#endregion
//#region scripts/crabbox-staging-artifacts.mts
const outputNames = ["captures", "runs"];
const maxEntries = 1e5;
const sha256 = /^[a-f0-9]{64}$/u;
function artifactPath$1(path) {
const parts = path.split("/");
return path.length <= 4096 && !isAbsolute(path) && !path.includes("\\") && !path.includes("\0") && outputNames.some((name) => parts[0] === name) && parts.every((part) => part && part !== "." && part !== "..");
}
const crabboxArtifactIdentitySchema = strictObject({
dev: string(),
ino: string()
});
const entrySchema$1 = discriminatedUnion("kind", [strictObject({
path: string().refine(artifactPath$1),
kind: literal("directory")
}), strictObject({
path: string().refine((path) => artifactPath$1(path) && path.includes("/")),
kind: literal("file"),
bytes: number().int().min(0).max(Number.MAX_SAFE_INTEGER),
sha256: string().regex(sha256)
})]);
const evidenceFields = {
version: literal(1),
durable: boolean(),
sourceIdentity: crabboxArtifactIdentitySchema,
entries: array(entrySchema$1).max(maxEntries)
};
const crabboxArtifactEvidenceSchema = discriminatedUnion("kind", [strictObject({
...evidenceFields,
kind: literal("none")
}), strictObject({
...evidenceFields,
kind: literal("copied"),
repository: strictObject({
path: string(),
identity: crabboxArtifactIdentitySchema
}),
parents: strictObject({
crabbox: crabboxArtifactIdentitySchema,
wrapperArtifacts: crabboxArtifactIdentitySchema
}),
destination: strictObject({
path: string(),
identity: crabboxArtifactIdentitySchema
})
})]);
function identity$1(stat) {
return {
dev: String(stat.dev),
ino: String(stat.ino)
};
}
function sameIdentity$1(stat, expected) {
return String(stat.dev) === expected.dev && String(stat.ino) === expected.ino;
}
function directory(path, expected) {
const stat = lstatSync(path, { bigint: true });
if (!stat.isDirectory() || expected && !sameIdentity$1(stat, expected)) throw new Error("artifact directory is missing, replaced, or not a real directory: " + path);
return stat;
}
function optionalDirectory(path) {
const stat = lstatSync(path, {
bigint: true,
throwIfNoEntry: false
});
if (stat && !stat.isDirectory()) throw new Error("artifact path must be a real directory: " + path);
return stat;
}
function sameFile(before, after) {
return before.dev === after.dev && before.ino === after.ino && before.mode === after.mode && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs;
}
function names(path) {
const found = readdirSync(path, { encoding: "buffer" });
if (found.length > maxEntries) throw new Error("artifact directory exceeds its entry limit");
return found.map((name) => {
if (!isUtf8(name)) throw new Error("artifact filename is not UTF-8");
return name.toString("utf8");
}).toSorted();
}
function privateDirectory(path) {
mkdirSync(path, { mode: 448 });
chmodSync(path, 448);
return identity$1(directory(path));
}
function hashFile(path, expected, buffer, target, nondurable) {
const input = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
let output;
try {
const before = fstatSync(input, { bigint: true });
if (!before.isFile() || !sameFile(before, expected) || before.size > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error("artifact file changed or is not a supported regular file: " + path);
if (target !== void 0) {
output = openSync(target, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 384);
fchmodSync(output, 384);
}
const hash = createHash("sha256");
let remaining = Number(before.size);
while (remaining > 0) {
const count = readSync(input, buffer, 0, Math.min(buffer.length, remaining), null);
if (!count) throw new Error("artifact file became shorter while reading: " + path);
hash.update(buffer.subarray(0, count));
if (output !== void 0) for (let written = 0; written < count;) {
const size = writeSync(output, buffer, written, count - written);
if (!size) throw new Error("artifact copy made no progress: " + target);
written += size;
}
remaining -= count;
}
if (!sameFile(before, fstatSync(input, { bigint: true })) || !sameFile(before, lstatSync(path, { bigint: true }))) throw new Error("artifact file changed while reading: " + path);
if (output !== void 0) {
if (!flushDescriptor(output)) nondurable?.();
}
return {
bytes: Number(before.size),
sha256: hash.digest("hex")
};
} finally {
try {
if (output !== void 0) closeSync(output);
} finally {
closeSync(input);
}
}
}
function inventory$1(root, options = {}) {
const entries = [];
const buffer = Buffer.alloc(65536);
const rootStat = optionalDirectory(root);
if (!rootStat) return entries;
if (options.destination && process.platform !== "win32" && (rootStat.mode & 511n) !== 448n) throw new Error("preserved artifact destination permissions changed");
if (options.destination && names(root).some((name) => !outputNames.some((output) => output === name))) throw new Error("preserved artifact destination gained an unexpected entry");
const walk = (path, relativePath, target, depth = 0) => {
if (depth > 128) throw new Error("artifact directory nesting exceeds its inspection limit");
if (!artifactPath$1(relativePath) || entries.length >= maxEntries) throw new Error("artifact inventory contains an unsupported path or exceeds its entry limit");
const before = lstatSync(path, { bigint: true });
if (before.isDirectory()) {
if (options.destination && process.platform !== "win32" && (before.mode & 511n) !== 448n) throw new Error("preserved artifact directory permissions changed: " + path);
const entry = {
path: relativePath,
kind: "directory"
};
entries.push(entry);
if (target) {
privateDirectory(join(target.root, relativePath));
target.copied.push(entry);
}
for (const name of names(path)) walk(join(path, name), relativePath + "/" + name, target, depth + 1);
if (!sameFile(before, lstatSync(path, { bigint: true }))) throw new Error("artifact directory changed while reading: " + path);
} else if (before.isFile()) {
if (options.destination && process.platform !== "win32" && (before.mode & 511n) !== 384n) throw new Error("preserved artifact file permissions changed: " + path);
const entry = {
path: relativePath,
kind: "file",
...hashFile(path, before, buffer, target && join(target.root, relativePath), target?.nondurable)
};
entries.push(entry);
target?.copied.push(entry);
} else throw new Error("artifact must be a regular file or real directory: " + path);
};
for (const name of outputNames) {
const path = join(root, name);
if (optionalDirectory(path)) walk(path, name, names(path).length > 0 ? options.target?.() : void 0);
}
if (!sameFile(rootStat, directory(root, identity$1(rootStat)))) throw new Error("artifact root changed during inspection");
return entries.toSorted((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
}
function sourceInventory(source, expected, target) {
const before = directory(source, expected);
const entries = inventory$1(join(source, ".crabbox"), { target });
if (!sameFile(before, directory(source, expected))) throw new Error("artifact source checkout changed during inspection");
return entries;
}
function copiedEntries(entries) {
const roots = new Set(entries.filter((entry) => entry.path.includes("/")).map((entry) => entry.path.split("/")[0]));
return entries.filter((entry) => roots.has(entry.path.split("/")[0]));
}
function sameInventory(actual, expected, allowMissing = false) {
const recorded = new Map(expected.map((entry) => [entry.path, entry]));
if (recorded.size !== expected.length || actual.some((entry) => JSON.stringify(recorded.get(entry.path)) !== JSON.stringify(entry)) || !allowMissing && actual.length !== expected.length) throw new Error("artifact layout or bytes do not match the preservation evidence");
}
function overlaps$1(left, right) {
const contains = (parent, child) => {
const path = relative(parent, child);
return path === "" || !isAbsolute(path) && path !== ".." && !path.startsWith(".." + sep);
};
return contains(left, right) || contains(right, left);
}
function verifyDestination(sourceCheckout, evidence, partial = false) {
const repository = evidence.repository.path;
const retainedRoot = join(repository, ".crabbox", "wrapper-artifacts");
if (!isAbsolute(repository) || realpathSync(repository) !== repository || dirname(evidence.destination.path) !== retainedRoot || !basename(evidence.destination.path).startsWith("run-") || overlaps$1(sourceCheckout, evidence.destination.path)) throw new Error("artifact preservation destination is not independent of the disposable checkout");
directory(repository, evidence.repository.identity);
directory(join(repository, ".crabbox"), evidence.parents.crabbox);
directory(retainedRoot, evidence.parents.wrapperArtifacts);
const stat = directory(evidence.destination.path, evidence.destination.identity);
if (process.platform !== "win32" && (stat.mode & 511n) !== 448n) throw new Error("preserved artifact destination permissions changed");
sameInventory(inventory$1(evidence.destination.path, { destination: true }), partial ? evidence.entries : copiedEntries(evidence.entries));
directory(repository, evidence.repository.identity);
directory(join(repository, ".crabbox"), evidence.parents.crabbox);
directory(retainedRoot, evidence.parents.wrapperArtifacts);
directory(evidence.destination.path, evidence.destination.identity);
}
/** Revalidate saved outputs; only missing source entries can be tolerated after partial disposal. */
function verifyPreservedCrabboxArtifacts(sourceCheckout, value, allowMissing = false) {
const evidence = crabboxArtifactEvidenceSchema.parse(value);
const sourceStat = optionalDirectory(sourceCheckout);
const source = sourceStat ? realpathSync(sourceCheckout) : resolve(sourceCheckout);
if (sourceStat && !sameIdentity$1(sourceStat, evidence.sourceIdentity)) throw new Error("artifact source checkout was replaced");
if (evidence.kind === "none") {
if (copiedEntries(evidence.entries).length !== 0) throw new Error("no-output evidence contains artifacts requiring preservation");
} else verifyDestination(source, evidence);
sameInventory(sourceStat ? sourceInventory(source, evidence.sourceIdentity) : [], evidence.entries, allowMissing);
if (sourceStat) directory(source, evidence.sourceIdentity);
}
function flushDescriptor(fd) {
try {
fsyncSync(fd);
return true;
} catch (error) {
if ([
"EINVAL",
"ENOTSUP",
"EOPNOTSUPP",
"ENOSYS"
].includes(error.code ?? "")) return false;
throw error;
}
}
function flushDirectory(path) {
if (process.platform === "win32") return false;
let fd;
try {
fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_DIRECTORY);
return flushDescriptor(fd);
} catch (error) {
if ([
"EINVAL",
"ENOTSUP",
"EOPNOTSUPP",
"ENOSYS"
].includes(error.code ?? "")) return false;
throw error;
} finally {
if (fd !== void 0) closeSync(fd);
}
}
/** Copy only native run/capture outputs into a fresh, private original-repository destination. */
function preserveCrabboxArtifacts(sourceCheckout, repositoryRoot, expectedRepositoryIdentity) {
if (sourceCheckout === repositoryRoot) return;
const sourceIdentity = identity$1(directory(sourceCheckout));
const source = realpathSync(sourceCheckout);
const state = {};
const completed = [];
try {
const entries = sourceInventory(source, sourceIdentity, () => {
if (!state.copied) {
const repositoryIdentity = identity$1(directory(repositoryRoot, expectedRepositoryIdentity));
const repository = realpathSync(repositoryRoot);
const crabbox = join(repository, ".crabbox");
const retainedRoot = join(crabbox, "wrapper-artifacts");
if (overlaps$1(source, retainedRoot)) throw new Error("artifact preservation destination overlaps the disposable checkout");
for (const path of [crabbox, retainedRoot]) if (!optionalDirectory(path)) privateDirectory(path);
const destination = mkdtempSync(join(retainedRoot, "run-"));
chmodSync(destination, 448);
state.copied = {
version: 1,
durable: process.platform !== "win32",
kind: "copied",
sourceIdentity,
entries: [],
repository: {
path: repository,
identity: repositoryIdentity
},
parents: {
crabbox: identity$1(directory(crabbox)),
wrapperArtifacts: identity$1(directory(retainedRoot))
},
destination: {
path: destination,
identity: identity$1(directory(destination))
}
};
}
return {
root: state.copied.destination.path,
copied: completed,
nondurable: () => {
state.copied.durable = false;
}
};
});
directory(source, sourceIdentity);
sameInventory(sourceInventory(source, sourceIdentity), entries);
const copied = state.copied;
if (!copied) return {
version: 1,
durable: true,
kind: "none",
sourceIdentity,
entries
};
copied.entries = entries;
verifyDestination(source, copied);
for (const entry of completed.toReversed()) if (entry.kind === "directory") copied.durable = flushDirectory(join(copied.destination.path, entry.path)) && copied.durable;
for (const path of [
copied.destination.path,
dirname(copied.destination.path),
join(copied.repository.path, ".crabbox"),
copied.repository.path
]) copied.durable = flushDirectory(path) && copied.durable;
directory(source, sourceIdentity);
console.error(`[crabbox] preserved temporary artifacts: ${join(source, ".crabbox")} -> ${relative(repositoryRoot, copied.destination.path)}`);
return copied;
} catch (error) {
const copied = state.copied;
if (copied) try {
verifyDestination(source, {
...copied,
entries: completed
}, true);
rmSync(copied.destination.path, { recursive: true });
} catch {
throw new Error("artifact preservation failed; partial output may remain at " + copied.destination.path, { cause: error });
}
throw error;
}
}
//#endregion
//#region scripts/crabbox-staging-claims.mts
const stdoutLimit = 4194304;
const stderrLimit = 65536;
const commandTimeoutMs = 5e3;
const inspectionBudgetMs = 1e4;
const pathSchema = string().min(1).max(8192).refine((path) => isAbsolute(path) && !path.includes("\0"));
const claimNamespaceSchema = strictObject({
version: literal(1),
platform: string(),
cwd: pathSchema,
directory: pathSchema,
anchor: strictObject({
path: pathSchema,
dev: string(),
ino: string()
})
});
const inventorySchema = object({
version: literal(1),
source: literal("local-claims"),
claims: array(object({
leaseId: string().min(1).max(512),
repoRoot: union([literal(""), pathSchema])
})).max(1e4),
problems: array(unknown()).max(100)
});
var ClaimInventoryHold = class extends Error {
constructor(reason, matchingLeaseIds) {
super(reason);
this.matchingLeaseIds = matchingLeaseIds;
}
};
function envValue(env, key) {
if (process.platform !== "win32") return env[key] ?? "";
const values = Object.entries(env).filter(([name]) => name.toUpperCase() === key.toUpperCase()).map(([, value]) => value ?? "");
if (new Set(values).size > 1) throw new ClaimInventoryHold("The native claims environment has ambiguous location variables.");
return values[0] ?? "";
}
function nativeLocation(cwd, env) {
let key;
let value = envValue(env, "XDG_STATE_HOME");
let suffix;
if (value !== "") {
key = "XDG_STATE_HOME";
suffix = ["crabbox", "claims"];
} else if (process.platform === "win32") {
key = "AppData";
value = envValue(env, key);
suffix = [
"crabbox",
"state",
"claims"
];
} else if (process.platform === "darwin") {
key = "HOME";
value = envValue(env, key);
suffix = [
"Library",
"Application Support",
"crabbox",
"state",
"claims"
];
} else {
key = "XDG_CONFIG_HOME";
value = envValue(env, key);
if (value !== "") {
if (!isAbsolute(value)) throw new ClaimInventoryHold("Native claims require an absolute XDG_CONFIG_HOME.");
suffix = [
"crabbox",
"state",
"claims"
];
} else {
key = "HOME";
value = envValue(env, key);
suffix = [
".config",
"crabbox",
"state",
"claims"
];
}
}
if (!value || value.includes("\0")) throw new ClaimInventoryHold("The native claims state location is unavailable.");
if (process.platform === "win32" && /^[a-z]:(?:[^\\/]|$)/iu.test(value)) throw new ClaimInventoryHold("A drive-relative native claims location cannot be preserved safely.");
const base = resolve(cwd, value);
return {
key,
base,
directory: join(base, ...suffix)
};
}
function directoryLocation(path) {
let ancestor = resolve(path);
const missing = [];
for (let depth = 0; depth < 128; depth += 1) {
if (lstatSync(ancestor, {
bigint: true,
throwIfNoEntry: false
})) {
const physical = realpathSync(ancestor);
const stat = statSync(physical, { bigint: true });
if (!stat.isDirectory()) throw new ClaimInventoryHold("A native claims path is not a readable directory.");
return {
directory: resolve(physical, ...missing),
anchor: {
path: physical,
dev: String(stat.dev),
ino: String(stat.ino)
},
generation: `${stat.mode}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`
};
}
const parent = dirname(ancestor);
if (parent === ancestor) break;
missing.unshift(relative(parent, ancestor));
ancestor = parent;
}
throw new ClaimInventoryHold("The native claims directory cannot be established.");
}
/** Bind discovery to the original native child's location without creating state. */
function captureClaimNamespace(cwd, env = process.env) {
const originalCwd = realpathSync(cwd);
if (!statSync(originalCwd).isDirectory()) throw new ClaimInventoryHold("The original native working directory is unavailable.");
const location = directoryLocation(nativeLocation(originalCwd, env).directory);
return claimNamespaceSchema.parse({
version: 1,
platform: process.platform,
cwd: originalCwd,
directory: location.directory,
anchor: location.anchor
});
}
function inspectNamespace(namespace, env) {
if (namespace.platform !== process.platform) throw new ClaimInventoryHold("The native claims namespace belongs to a different platform.");
const anchor = lstatSync(namespace.anchor.path, { bigint: true });
if (!anchor.isDirectory() || String(anchor.dev) !== namespace.anchor.dev || String(anchor.ino) !== namespace.anchor.ino || realpathSync(namespace.anchor.path) !== namespace.anchor.path) throw new ClaimInventoryHold("The original native claims namespace was replaced.");
const selected = nativeLocation(namespace.cwd, env);
const current = directoryLocation(selected.directory);
if (current.directory !== namespace.directory) throw new ClaimInventoryHold("The native claims state location changed since staging was created.");
return {
selected,
current
};
}
function childEnvironment(env, key, base) {
const result = { ...env };
for (const name of Object.keys(result)) if (name === key || process.platform === "win32" && name.toUpperCase() === key.toUpperCase()) delete result[name];
result[key] = base;
return result;
}
function within(root, path) {
const part = relative(root, path);
return part === "" || !isAbsolute(part) && part !== ".." && !part.startsWith(".." + sep);
}
/** Read the native public inventory; absence is not a provider-liveness claim. */
async function verifyNoStagingClaims(params) {
try {
params.signal?.throwIfAborted();
const parsedNamespace = claimNamespaceSchema.safeParse(params.namespace);
if (!parsedNamespace.success) throw new ClaimInventoryHold("The recorded native claims namespace is invalid.");
const namespace = parsedNamespace.data;
const env = { ...params.env ?? process.env };
const before = inspectNamespace(namespace, env);
if (!isAbsolute(params.sourceRoot) || params.sourceRoot.includes("\0")) throw new ClaimInventoryHold("The staging source path must be absolute.");
const sourceRoot = directoryLocation(params.sourceRoot).directory;
const deadline = Date.now() + inspectionBudgetMs;
const abort = new AbortController();
const signal = params.signal ? AbortSignal.any([params.signal, abort.signal]) : abort.signal;
let captureFailure;
const output = Buffer.alloc(stdoutLimit);
let stdoutBytes = 0;
let stderrBytes = 0;
const exceedLimit = () => {
captureFailure ??= new ClaimInventoryHold("Native claim inventory exceeded its output limit.");
abort.abort(captureFailure);
};
let status;
try {
status = await runManagedCommand({
bin: params.binary,
args: [
"claims",
"list",
"--json"
],
cwd: params.cwd,
env: childEnvironment(env, before.selected.key, before.selected.base),
stdio: [
"ignore",
"pipe",
"pipe"
],
timeoutMs: commandTimeoutMs,
signal,
requireProcessTreeExit: process.platform !== "win32",
onReady(child) {
if (!child.stdout || !child.stderr) throw new ClaimInventoryHold("Native claim inventory output is unavailable.");
child.stdout.on("data", (chunk) => {
if (captureFailure) return;
if (stdoutBytes + chunk.length > stdoutLimit) {
exceedLimit();
return;
}
stdoutBytes += chunk.copy(output, stdoutBytes);
});
child.stderr.on("data", (chunk) => {
stderrBytes += chunk.length;
if (stderrBytes > stderrLimit) exceedLimit();
});
}
});
} catch (error) {
if (captureFailure && captureFailure !== error) throw new AggregateError([captureFailure, error], captureFailure.message, { cause: error });
throw error;
}
if (captureFailure) throw captureFailure;
if (status !== 0) throw new ClaimInventoryHold("Native claim inventory failed or returned only partial results.");
const bytes = output.subarray(0, stdoutBytes);
let document;
try {
if (!isUtf8(bytes)) throw new Error("invalid encoding");
document = JSON.parse(bytes.toString("utf8"));
} catch {
throw new ClaimInventoryHold("Native claim inventory did not return valid JSON.");
}
const parsed = inventorySchema.safeParse(document);
if (!parsed.success) throw new ClaimInventoryHold("Native claim inventory has an unsupported or malformed schema.");
if (parsed.data.problems.length > 0) throw new ClaimInventoryHold("Native claim inventory reports unreadable or invalid local records.");
const matches = /* @__PURE__ */ new Set();
for (const claim of parsed.data.claims) {
if (Date.now() >= deadline) throw new ClaimInventoryHold("Native claim inventory exceeded its inspection budget.");
if (claim.repoRoot && within(sourceRoot, directoryLocation(claim.repoRoot).directory)) {
matches.add(claim.leaseId);
if (matches.size === 16) break;
}
}
if (matches.size > 0) throw new ClaimInventoryHold("Local claims still name this staging source; stop or reclaim the matching leases before retrying.", [...matches]);
const after = inspectNamespace(namespace, env);
if (JSON.stringify(after.current) !== JSON.stringify(before.current)) throw new ClaimInventoryHold("The native claims namespace changed during inventory.");
params.signal?.throwIfAborted();
return { ok: true };
} catch (error) {
return {
ok: false,
reason: error instanceof ClaimInventoryHold ? error.message : "Native claim inventory could not be verified.",
error,
...hasUnjoinedWork(error) ? { unjoined: true } : {},
...error instanceof ClaimInventoryHold && error.matchingLeaseIds ? { matchingLeaseIds: error.matchingLeaseIds } : {}
};
}
}
//#endregion
//#region scripts/crabbox-staging-location.mts
const stagingPrefix = "openclaw-crabbox-sync-";
const gitRoutingKeys = /* @__PURE__ */ new Set([
"GIT_DIR",
"GIT_WORK_TREE",
"GIT_CEILING_DIRECTORIES",
"GIT_DISCOVERY_ACROSS_FILESYSTEM"
]);
function prospectiveDirectory(directory) {
let ancestor = resolve(directory);
const missing = [];
for (let depth = 0; depth < 128; depth += 1) try {
const physical = realpathSync(ancestor);
if (!statSync(physical).isDirectory()) return;
accessSync(physical, constants.R_OK | constants.X_OK);
return resolve(physical, ...missing);
} catch (error) {
if (error.code !== "ENOENT") return;
if (lstatSync(ancestor, { throwIfNoEntry: false })) return;
const parent = dirname(ancestor);
if (parent === ancestor) return;
missing.unshift(basename(ancestor));
ancestor = parent;
}
}
function overlaps(left, right) {
const foldCase = process.platform === "darwin" || process.platform === "win32";
const leftPath = foldCase ? left.toLowerCase() : left;
const rightPath = foldCase ? right.toLowerCase() : right;
const contains = (parent, child) => {
const path = relative(parent, child);
return path === "" || !isAbsolute(path) && path !== ".." && !path.startsWith(`..${sep}`);
};
return contains(leftPath, rightPath) || contains(rightPath, leftPath);
}
/**
* Optional recovery registration; false must never prevent ordinary staging.
* This checks the selected source/workspace only. Arbitrary extra host mounts
* are not isolated by recovery registration, and no host tree is traversed.
*/
function canRecordStaging(exactProspectiveStageRoot, repository, env = process.env) {
try {
const source = realpathSync(repository);
if (!statSync(source).isDirectory()) return false;
accessSync(source, constants.R_OK | constants.X_OK);
const stage = prospectiveDirectory(exactProspectiveStageRoot);
if (!stage || overlaps(stage, source)) return false;
for (const [key, value] of Object.entries(env)) {
const upper = key.toUpperCase();
if (value && (upper === "GIT_DIR" || upper === "GIT_WORK_TREE") && !isAbsolute(value)) return false;
}
const gitEnv = Object.fromEntries(Object.entries(env).filter(([key]) => {
const upper = key.toUpperCase();
return !upper.startsWith("GIT_") || gitRoutingKeys.has(upper);
}));
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
cwd: source,
env: {
...gitEnv,
GIT_OPTIONAL_LOCKS: "0",
GIT_TERMINAL_PROMPT: "0"
},
stdio: [
"ignore",
"pipe",
"pipe"
],
timeout: 5e3,
killSignal: "SIGKILL",
maxBuffer: 1048576
});
if (result.error || result.status !== 0 || !isUtf8(result.stdout)) return false;
const workspace = result.stdout.toString("utf8").replace(/\r?\n$/u, "");
if (!isAbsolute(workspace)) return false;
const physicalWorkspace = realpathSync(workspace);
if (!statSync(physicalWorkspace).isDirectory()) return false;
accessSync(physicalWorkspace, constants.R_OK | constants.X_OK);
return !overlaps(stage, physicalWorkspace);
} catch {
return false;
}
}
//#endregion
//#region scripts/crabbox-staging.mts
const prefix = stagingPrefix;
const receiptName = "staging.json";
const manifestName = "manifest.json";
const cursorName = prefix + "discovery";
const headerLimit = 32768;
const manifestLimit = 67108864;
const identitySchema = crabboxArtifactIdentitySchema;
const witnessSchema = strictObject({
gitDir: string(),
ref: string(),
commit: string().regex(/^[a-f0-9]{40}$/u)
});
const receiptSchema = strictObject({
version: literal(2),
id: uuid(),
ownerPid: number().int().min(2),
ownerDomain: string().regex(/^[a-f0-9]{64}$/u).optional(),
repository: string(),
repositoryIdentity: identitySchema.optional(),
claims: claimNamespaceSchema.optional(),
leases: array(string().min(1).max(512)).max(16).optional(),
kind: _enum(["capsule", "worktree"]),
rootIdentity: identitySchema,
payloadIdentity: identitySchema,
durable: boolean(),
users: _enum([
"none",
"admitted",
"settled"
]),
state: _enum([
"preparing",
"prepared",
"admitted",
"settled",
"preserved",
"removing"
]),
manifest: string().regex(/^[a-f0-9]{64}$/u).optional(),
witness: witnessSchema.optional(),
artifactManifest: string().regex(/^[a-f0-9]{64}$/u).optional(),
mirror: strictObject({
key: string().regex(/^[a-f0-9]{64}$/u),
slotIdentity: identitySchema,
idle: boolean(),
disposing: literal(true).optional(),
lastUsed: number().int().nonnegative(),
database: string().regex(/^[a-f0-9]{64}$/u).optional()
}).optional(),
hold: _enum([
"artifacts",
"claims",
"writers",
"registration"
]).optional()
});
const disposalSchema = strictObject({
version: literal(1),
id: uuid(),
key: string().regex(/^[a-f0-9]{64}$/u),
slotIdentity: identitySchema,
receipt: receiptSchema.optional()
});
const entrySchema = strictObject({
path: string().min(1),
kind: _enum([
"file",
"symlink",
"directory"
]),
mode: _enum([
"100644",
"100755",
"120000"
]).optional(),
blob: string().regex(/^[a-f0-9]{40}$/u).optional()
});
const sourceEntrySchema = strictObject({
path: string().min(1),
mode: _enum([
"100644",
"100755",
"120000"
]),
blob: string().regex(/^[a-f0-9]{40}$/u)
});
const manifestSchema = strictObject({
source: strictObject({
files: array(sourceEntrySchema),
deleted: array(string())
}),
entries: array(entrySchema),
artifacts: crabboxArtifactEvidenceSchema.optional()
});
let cachedProcessDomain;
function processDomain() {
if (cachedProcessDomain !== void 0) return cachedProcessDomain ?? void 0;
try {
let boot;
let namespace = "";
if (process.platform === "linux") {
const fd = openSync("/proc/sys/kernel/random/boot_id", constants.O_RDONLY | constants.O_NONBLOCK);
try {
const bytes = Buffer.alloc(128);
boot = bytes.subarray(0, readSync(fd, bytes)).toString("utf8").trim();
} finally {
closeSync(fd);
}
namespace = readlinkSync("/proc/self/ns/pid");
if (!/^pid:\[\d+\]$/u.test(namespace)) throw new Error("Process namespace identity is unavailable.");
} else if (process.platform === "darwin") {
const result = spawnSync("/usr/sbin/sysctl", ["-n", "kern.bootsessionuuid"], {
encoding: "utf8",
env: {},
timeout: 1e3,
maxBuffer: 1024
});
if (result.error || result.status !== 0) throw new Error("Boot session identity is unavailable.");
boot = result.stdout.trim();
} else throw new Error("Process domain identity is unsupported.");
if (!uuid().safeParse(boot.toLowerCase()).success) throw new Error("Boot session identity is invalid.");
cachedProcessDomain = createHash("sha256").update(process.platform + ":" + boot.toLowerCase() + ":" + namespace).digest("hex");
} catch {
cachedProcessDomain = null;
}
return cachedProcessDomain ?? void 0;
}
function identity(path) {
const stat = lstatSync(path, { bigint: true });
if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("staging directory was replaced: " + path);
return {
dev: String(stat.dev),
ino: String(stat.ino)
};
}
function sameIdentity(left, right) {
return left.dev === right.dev && left.ino === right.ino;
}
function assertIdentity(path, expected) {
if (!sameIdentity(identity(path), expected)) throw new Error("staging directory identity changed: " + path);
}
function safeRelative(path) {
return !isAbsolute(path) && !path.includes("\\") && !path.includes("\0") && path.split("/").every((part) => part !== "" && part !== "." && part !== "..");
}
function readBounded(path, limit) {
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
try {
const before = fstatSync(fd, { bigint: true });
if (!before.isFile() || before.size > BigInt(limit)) throw new Error("staging metadata is not a bounded regular file");
const bytes = Buffer.alloc(Number(before.size));
for (let offset = 0; offset < bytes.length;) {
const count = readSync(fd, bytes, offset, bytes.length - offset, null);
if (!count) throw new Error("staging metadata became shorter while reading");
offset += count;
}
const after = fstatSync(fd, { bigint: true });
if (before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs) throw new Error("staging metadata changed while reading");
return bytes;
} finally {
closeSync(fd);
}
}
function writeAtomic(root, name, bytes, durable = true) {
const temporary = join(root, "." + name + "." + randomUUID());
try {
let fileDurable = false;
const fd = openSync(temporary, "wx", 384);
try {
writeFileSync(fd, bytes);
fileDurable = durable && flushDescriptor(fd);
} finally {
closeSync(fd);
}
renameSync(temporary, join(root, name));
return fileDurable && flushDirectory(root);
} finally {
rmSync(temporary, { force: true });
}
}
function blob(path, symbolic) {
if (symbolic) {
const bytes = readlinkSync(path, { encoding: "buffer" });
return createHash("sha1").update("blob " + bytes.length + "\0").update(bytes).digest("hex");
}
return regularFileDigest(path, (size) => createHash("sha1").update("blob " + size + "\0"));
}
function regularFileDigest(path, initialize) {
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
try {
const before = fstatSync(fd, { bigint: true });
if (!before.isFile()) throw new Error("staging contains an unsupported file");
const hash = initialize(before.size);
const buffer = Buffer.alloc(65536);
for (;;) {
const count = readSync(fd, buffer);
if (!count) break;
hash.update(buffer.subarray(0, count));
}
const after = fstatSync(fd, { bigint: true });
if (before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs) throw new Error("staging content changed while reading");
return hash.digest("hex");
} finally {
closeSync(fd);
}
}
function artifactPath(path) {
return path === "source/.crabbox" || ["source/.crabbox/runs", "source/.crabbox/captures"].some((root) => path === root || path.startsWith(root + "/"));
}
function inventory(payload, known = /* @__PURE__ */ new Map(), preservedArtifacts = false, observeEntry) {
const entries = [];
const walk = (directory, parent) => {
for (const name of readdirSync(directory)) {
const path = parent ? parent + "/" + name : name;
if (preservedArtifacts && artifactPath(path) && path !== "source/.crabbox") continue;
if (!safeRelative(path)) throw new Error("staging contains an unsupported path");
const absolute = join(payload, path);
const stat = lstatSync(absolute);
observeEntry?.(path, stat);
if (stat.isDirectory()) {
if (!preservedArtifacts || path !== "source/.crabbox") entries.push({
path,
kind: "directory"
});
walk(absolute, path);
} else if (stat.isFile() || stat.isSymbolicLink()) {
const symbolic = stat.isSymbolicLink();
const mode = symbolic ? "120000" : stat.mode & 64 ? "100755" : "100644";
const frozen = known.get(path);
if (frozen && frozen.mode !== mode) throw new Error("source mode changed before sealing: " + path);
entries.push({
path,
kind: symbolic ? "symlink" : "file",
mode,
blob: frozen?.blob ?? blob(absolute, symbolic)
});
} else throw new Error("staging contains an unsupported file kind: " + path);
}
};
walk(payload, "");
return entries.toSorted((a, b) => a.path.localeCompare(b.path));
}
function readReceipt(root) {
identity(root);
let receipt;
try {
receipt = receiptSchema.parse(JSON.parse(readBounded(join(root, receiptName), headerLimit).toString("utf8")));
} catch {
throw new Error("staging receipt has unknown or invalid metadata");
}
if (basename(root) !== prefix + receipt.id) throw new Error("staging generation does not match its directory");
assertIdentity(root, receipt.rootIdentity);
return receipt;
}
function ownerAbsent(pid) {
try {
process.kill(pid, 0);
return false;
} catch (error) {
return error.code === "ESRCH";
}
}
function createStaging(syncRoot, repository, kind = "capsule") {
const id = randomUUID();
mkdirSync(syncRoot, { recursive: true });
const root = join(realpathSync(syncRoot), prefix + id);
mkdirSync(root, { mode: 448 });
const recorded = canRecordStaging(root, repository);
const payload = join(root, "payload");
let receipt;
try {
mkdirSync(payload, { mode: 448 });
receipt = {
version: 2,
id,
ownerPid: process.pid,
ownerDomain: recorded ? processDomain() : void 0,
repository: realpathSync(repository),
repositoryIdentity: identity(realpathSync(repository)),
kind,
rootIdentity: identity(root),
payloadIdentity: identity(payload),
durable: recorded && flushDirectory(root) && flushDirectory(dirname(root)),
users: "none",
state: "preparing"
};
if (recorded && !writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n", receipt.durable) && receipt.durable) {
receipt.durable = false;
writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n", false);
}
} catch (error) {
try {
rmSync(root, {
recursive: true,
force: true
});
} catch (cleanupError) {
throw new AggregateError([error, cleanupError], "Staging preparation failed; allocation retained at " + root, { cause: cleanupError });
}
throw error;
}
return stagingHandle(root, receipt, recorded);
}
function stagingHandle(root, initialReceipt, recorded) {
let receipt = initialReceipt;
const payload = join(root, "payload");
const update = (fields) => {
assertIdentity(root, receipt.rootIdentity);
receipt = {
...receipt,
...fields
};
if (!recorded) return;
if (!writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n", receipt.durable) && receipt.durable) {
receipt.durable = false;
writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n", false);
}
};
let disposed = false;
return {
recorded,
root,
payload,
prepared(source, witness, observeEntry) {
if (!recorded) return;
const known = new Map(source.files.map((entry) => ["source/" + entry.path, {
...entry,
path: "source/" + entry.path,
kind: entry.mode === "120000" ? "symlink" : "file"
}]));
const manifest = {
source,
entries: inventory(payload, known, false, observeEntry)
};
const bytes = JSON.stringify(manifest) + "\n";
if (Buffer.byteLength(bytes) > manifestLimit) throw new Error("staging manifest exceeds the recovery metadata limit");
const durable = writeAtomic(root, manifestName, bytes, receipt.durable);
let claims;
try {
claims = captureClaimNamespace(join(payload, "source"));
} catch {}
update({
durable,
claims,
state: "prepared",
manifest: createHash("sha256").update(bytes).digest("hex"),
witness
});
},
admitted: (claims, leases) => update({
state: "admitted",
users: "admitted",
claims,
leases
}),
settled: (leases) => update({
state: "settled",
users: "settled",
leases: leases ?? receipt.leases
}),
preserved(artifacts) {
if (!recorded) return;
assertIdentity(root, receipt.rootIdentity);
const saved = writeArtifactRecord(root, artifacts, receipt.durable);
update({
state: "preserved",
durable: saved.durable && receipt.durable && artifacts.durable,
artifactManifest: saved.digest
});
},
hold: (hold) => update({ hold: receipt.hold === "writers" ? "writers" : hold }),
dispose() {
if (disposed) return;
update({ state: "removing" });
assertIdentity(payload, receipt.payloadIdentity);
rmSync(payload, {
recursive: true,
force: true
});
rmSync(root, {
recursive: true,
force: true
});
disposed = true;
}
};
}
const mirrorLimit = 32;
const mirrorDatabase = "mirror.sqlite";
function privateMirrorDirectory(path) {
const stat = lstatSync(path);
if (!stat.isDirectory() || stat.isSymbolicLink() || (stat.mode & 63) !== 0 || process.getuid && stat.uid !== process.getuid()) throw new Error("source mirror directory is not private: " + path);
return identity(path);
}
function mirrorLock(path, waitForAllocation = false) {
const parent = dirname(path);
const parentIdentity = privateMirrorDirectory(parent);
try {
closeSync(openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_RDWR | constants.O_NOFOLLOW, 384));
} catch (error) {
if (error.code !== "EEXIST") throw error;
}
const captured = lstatSync(path, { bigint: true });
if (!captured.isFile() || captured.isSymbolicLink() || captured.nlink !== 1n || captured.size !== 0n || (captured.mode & 63n) !== 0n || process.getuid && captured.uid !== BigInt(process.getuid())) throw new Error("source mirror lock is not a private empty regular database");
let released = false;
const assertOwned = () => {
assertIdentity(parent, parentIdentity);
const current = lstatSync(path, { bigint: true });
if (!current.isFile() || current.isSymbolicLink() || current.nlink !== 1n || current.dev !== captured.dev || current.ino !== captured.ino || current.mode !== captured.mode || current.size !== 0n) throw new Error("source mirror lock ownership changed");
};
let database;
try {
database = new DatabaseSync(path, { timeout: 0 });
try {
database.exec("PRAGMA journal_mode=MEMORY; BEGIN EXCLUSIVE");
} catch (error) {
if (!waitForAllocation || !sqliteBusy(error)) throw error;
console.error("[crabbox] waiting for source mirror allocation...");
const deadline = performance.now() + 12e4;
database.exec("PRAGMA busy_timeout=120000");
database.exec("PRAGMA journal_mode=MEMORY");
const remaining = Math.max(0, Math.ceil(deadline - performance.now()));
database.exec(`PRAGMA busy_timeout=${remaining}`);
database.exec("BEGIN EXCLUSIVE");
}
assertOwned();
} catch (error) {
database?.close();
if (sqliteBusy(error)) return;
throw error;
}
const connection = database;
const release = () => {
if (released) return;
assertOwned();
connection.exec("ROLLBACK");
connection.close();
released = true;
};
const remove = () => {
if (!released) throw new Error("cannot remove an active source mirror lock");
assertOwned();
rmSync(path);
};
return Object.assign(release, {
assertOwned,
remove
});
}
function sqliteBusy(error) {
return typeof error === "object" && error !== null && "errcode" in error && error.errcode === 5;
}
function mirrorSlot(syncRoot, key, expectedId) {
const slot = join(syncRoot, "mirrors", key);
const slotIdentity = privateMirrorDirectory(slot);
if (readdirSync(slot).some((name) => name !== "stage" && name !== "lock")) throw new Error("source mirror slot has unknown metadata");
const id = lstatSync(join(slot, "stage"), { throwIfNoEntry: false }) ? readBounded(join(slot, "stage"), 128).toString("utf8").trim() : expectedId;
if (!id || !uuid().safeParse(id).success) throw new Error("source mirror slot has an invalid staging identity");
const root = join(syncRoot, prefix + id);
const { receipt, disposal } = readMirrorState(syncRoot, id);
if (receipt && (receipt.mirror?.key !== key || !sameIdentity(receipt.mirror.slotIdentity, slotIdentity))) throw new Error("source mirror staging ownership does not match its slot");
return {
slot,
slotIdentity,
root,
receipt,
disposal,
id
};
}
function idleMirror(receipt) {
return Boolean(receipt.mirror?.idle && receipt.durable && receipt.manifest && !receipt.hold && (receipt.users === "none" && receipt.state === "prepared" || receipt.users === "settled" && receipt.state === "preserved"));
}
function saveMirrorReceipt(root, receipt) {
assertIdentity(root, receipt.rootIdentity);
if (!writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n")) {
writeAtomic(root, receiptName, JSON.stringify({
...receipt,
durable: false,
mirror: receipt.mirror ? {
...receipt.mirror,
idle: false
} : void 0
}) + "\n", false);
throw new Error("source mirror ownership could not be recorded durably");
}
}
function databaseDigest(root, witness) {
for (const suffix of [
"-journal",
"-wal",
"-shm"
]) if (lstatSync(join(root, mirrorDatabase + suffix), { throwIfNoEntry: false })) throw new Error("source mirror database has unsettled journal state");
return regularFileDigest(join(root, mirrorDatabase), () => createHash("sha256").update(JSON.stringify(witness ?? null) + "\0"));
}
function disposalPath(syncRoot, id) {
return join(syncRoot, prefix + "disposal-" + id);
}
function readDisposal(syncRoot, id) {
const path = disposalPath(syncRoot, id);
const stat = lstatSync(path);
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1 || (stat.mode & 63) !== 0 || process.getuid && stat.uid !== process.getuid()) throw new Error("source mirror disposal record is not private");
const record = disposalSchema.parse(JSON.parse(readBounded(path, headerLimit).toString("utf8")));
const receipt = record.receipt;
if (record.id !== id || receipt && (receipt.id !== id || !receipt.mirror?.disposing || !idleMirror(receipt) || receipt.mirror.key !== record.key || !sameIdentity(receipt.mirror.slotIdentity, record.slotIdentity))) throw new Error("source mirror disposal record has invalid ownership");
return record;
}
function readMirrorState(syncRoot, id) {
const root = join(syncRoot, prefix + id);
const record = lstatSync(disposalPath(syncRoot, id), { throwIfNoEntry: false }) ? readDisposal(syncRoot, id) : void 0;
const present = lstatSync(root, { throwIfNoEntry: false });
if (record && present) {
if (!record.receipt) throw new Error("source mirror root appeared after empty-slot disposal was recorded");
assertIdentity(root, record.receipt.rootIdentity);
}
if (lstatSync(join(root, receiptName), { throwIfNoEntry: false })) {
const receipt = readReceipt(root);
if (record && JSON.stringify(record.receipt) !== JSON.stringify(receipt)) throw new Error("source mirror disposal record does not match its receipt");
return {
receipt,
disposal: record
};
}
if (record) {
if (present && readdirSync(root).length) throw new Error("source mirror lost its receipt before payload disposal completed");
return {
receipt: record.receipt,
disposal: record
};
}
return {
receipt: present ? readReceipt(root) : void 0,
disposal: void 0
};
}
function saveDisposal(syncRoot, input) {
const record = disposalSchema.parse(input);
const path = disposalPath(syncRoot, record.id);
if (lstatSync(path, { throwIfNoEntry: false })) {
if (JSON.stringify(readDisposal(syncRoot, record.id)) !== JSON.stringify(record)) throw new Error("source mirror disposal record changed");
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
try {
if (!flushDescriptor(fd) || !flushDirectory(syncRoot)) throw new Error("source mirror disposal record durability is unavailable");
} finally {
closeSync(fd);
}
} else if (!writeAtomic(syncRoot, basename(path), JSON.stringify(record) + "\n")) throw new Error("source mirror disposal record could not be recorded durably");
return record;
}
function removeDisposal(syncRoot, expected) {
if (JSON.stringify(readDisposal(syncRoot, expected.id)) !== JSON.stringify(expected)) throw new Error("source mirror disposal record changed");
if (!flushDirectory(join(syncRoot, "mirrors")) || !flushDirectory(syncRoot)) throw new Error("source mirror namespace removal could not be recorded durably");
rmSync(disposalPath(syncRoot, expected.id));
}
/** Claim under allocation; keep the slot reserved until its recorded disposal finishes. */
function claimIdleMirror(syncRoot, key, expectedId) {
const slot = join(syncRoot, "mirrors", key);
privateMirrorDirectory(slot);
if (!lstatSync(join(slot, "stage"), { throwIfNoEntry: false }) || !lstatSync(join(slot, "lock"), { throwIfNoEntry: false })) {
if (!expectedId) return;
const disposal = readDisposal(syncRoot, expectedId);
assertIdentity(slot, disposal.slotIdentity);
if (disposal.key !== key || lstatSync(join(syncRoot, prefix + expectedId), { throwIfNoEntry: false }) || readdirSync(slot).some((name) => name !== "lock")) throw new Error("source mirror terminal disposal ownership changed");
}
const release = mirrorLock(join(slot, "lock"));
if (!release) return;
try {
const current = mirrorSlot(syncRoot, key, expectedId);
if (expectedId && current.id !== expectedId || current.receipt && !idleMirror(current.receipt)) {
release();
return;
}
let disposal;
return {
release,
removePayload() {
release.assertOwned();
if (!current.receipt) {
if (lstatSync(current.root, { throwIfNoEntry: false })) throw new Error("source mirror root appeared before empty-slot disposal");
disposal = saveDisposal(syncRoot, {
version: 1,
id: current.id,
key,
slotIdentity: current.slotIdentity
});
return;
}
let receipt = current.receipt;
if (JSON.stringify(readMirrorState(syncRoot, current.id).receipt) !== JSON.stringify(receipt)) throw new Error("source mirror disposal ownership changed");
if (!lstatSync(join(current.root, receiptName), { throwIfNoEntry: false })) {
disposal = saveDisposal(syncRoot, readDisposal(syncRoot, current.id));
return;
}
const generations = recoveryMetadata(current.root, join(current.root, "payload", "source"));
const payload = join(current.root, "payload");
if (!receipt.mirror?.disposing || lstatSync(payload, { throwIfNoEntry: false })) assertIdentity(payload, receipt.payloadIdentity);
if (!receipt.mirror?.disposing) {
receipt = receiptSchema.parse({
...receipt,
mirror: {
...receipt.mirror,
disposing: true
}
});
saveMirrorReceipt(current.root, receipt);
}
disposal = saveDisposal(syncRoot, {
version: 1,
id: current.id,
key,
slotIdentity: current.slotIdentity,
receipt
});
release.assertOwned();
assertIdentity(current.root, receipt.rootIdentity);
for (const name of generations) rmSync(join(current.root, name));
if (generations.length && !flushDirectory(current.root)) throw new Error("source mirror metadata removal could not be recorded durably");
rmSync(payload, {
recursive: true,
force: true
});
for (const name of [
manifestName,
mirrorDatabase,
`${mirrorDatabase}-journal`,
`${mirrorDatabase}-wal`,
`${mirrorDatabase}-shm`
]) rmSync(join(current.root, name), { force: true });
},
removeSlot() {
release.assertOwned();
if (!disposal || JSON.stringify(readDisposal(syncRoot, current.id)) !== JSON.stringify(disposal)) throw new Error("source mirror disposal record changed before namespace removal");
const latest = mirrorSlot(syncRoot, key, current.id);
if (latest.id !== current.id || !sameIdentity(latest.slotIdentity, current.slotIdentity)) throw new Error("source mirror slot changed during disposal");
if (latest.receipt) {
if (JSON.stringify(latest.receipt) !== JSON.stringify(disposal.receipt)) throw new Error("source mirror disposal was not recorded");
if (lstatSync(current.root, { throwIfNoEntry: false })) {
assertIdentity(current.root, latest.receipt.rootIdentity);
if (readdirSync(current.root).some((name) => name !== receiptName)) throw new Error("source mirror disposal has remaining metadata");
rmSync(join(current.root, receiptName), { force: true });
rmdirSync(current.root);
}
} else if (lstatSync(current.root, { throwIfNoEntry: false })) throw new Error("source mirror root appeared during empty-slot disposal");
if (!flushDirectory(syncRoot)) throw new Error("source mirror root removal could not be recorded durably");
assertIdentity(slot, current.slotIdentity);
rmSync(join(slot, "stage"), { force: true });
if (!flushDirectory(slot)) throw new Error("source mirror slot handoff removal could not be recorded durably");
release();
release.remove();
rmdirSync(slot);
removeDisposal(syncRoot, disposal);
}
};
} catch (error) {
release();
throw error;
}
}
function allocateMirrorSlot(syncRoot, key) {
const mirrors = join(syncRoot, "mirrors");
const slot = join(mirrors, key);
let allocation;
const acquire = () => {
allocation = mirrorLock(join(mirrors, ".allocation.lock"), true);
if (!allocation) console.error("[crabbox] source mirror allocation is busy; using a fresh capsule");
return allocation;
};
try {
if (!acquire()) return;
const attempted = /* @__PURE__ */ new Set();
for (;;) {
let createdSlot = false;
if (!lstatSync(slot, { throwIfNoEntry: false })) {
const slots = readdirSync(mirrors).filter((name) => name !== ".allocation.lock");
if (slots.length >= mirrorLimit) {
const idle = slots.flatMap((name) => {
try {
if (!/^[a-f0-9]{64}$/u.test(name) || attempted.has(name)) return [];
const value = mirrorSlot(syncRoot, name);
return !value.receipt || idleMirror(value.receipt) ? [{
key: name,
lastUsed: value.receipt?.mirror?.lastUsed ?? 0
}] : [];
} catch {
return [];
}
}).toSorted((a, b) => a.lastUsed - b.lastUsed);
let victim;
for (const entry of idle) {
attempted.add(entry.key);
try {
victim = claimIdleMirror(syncRoot, entry.key);
if (victim) break;
} catch {}
}
if (!victim) {
console.error("[crabbox] source mirror limit reached; protected copies retained, using a fresh capsule");
return;
}
allocation();
allocation = void 0;
try {
victim.removePayload();
if (!acquire()) return;
victim.removeSlot();
} catch (error) {
console.error("[crabbox] source mirror eviction could not verify a candidate; retained it and checking later idle mirrors: " + (error instanceof Error ? error.message : String(error)));
} finally {
victim.release();
}
if (!allocation && !acquire()) return;
continue;
}
mkdirSync(slot, { mode: 448 });
createdSlot = true;
}
const slotIdentity = privateMirrorDirectory(slot);
const release = mirrorLock(join(slot, "lock"));
if (!release) {
console.error("[crabbox] source mirror is in use or has an unresolved owner; using a fresh capsule");
return;
}
return {
slot,
slotIdentity,
createdSlot,
release
};
}
} finally {
allocation?.();
}
}
/** Own one immutable command view, with a bounded disposable cache between runs. */
function createMirrorStaging(syncRootInput, repositoryInput) {
let release;
try {
if (!processDomain()) {
console.error("[crabbox] source mirror process ownership is unavailable; using a fresh capsule");
return;
}
mkdirSync(syncRootInput, { recursive: true });
const syncRoot = realpathSync(syncRootInput);
const repository = realpathSync(repositoryInput);
if (!canRecordStaging(join(syncRoot, prefix + "mirror"), repository)) return;
if (!flushDirectory(syncRoot)) {
console.error("[crabbox] durable source mirror ownership is unavailable; using a fresh capsule");
return;
}
const mirrors = join(syncRoot, "mirrors");
mkdirSync(mirrors, {
recursive: true,
mode: 448
});
privateMirrorDirectory(mirrors);
const key = createHash("sha256").update(repository).digest("hex");
const allocated = allocateMirrorSlot(syncRoot, key);
if (!allocated) return;
const { slot, slotIdentity, createdSlot } = allocated;
release = allocated.release;
let receipt;
let root;
if (!createdSlot && !lstatSync(join(slot, "stage"), { throwIfNoEntry: false })) throw new Error("source mirror slot has no recorded staging owner");
if (lstatSync(join(slot, "stage"), { throwIfNoEntry: false })) {
const previous = mirrorSlot(syncRoot, key);
receipt = previous.receipt;
root = previous.root;
if (previous.disposal || receipt && (!idleMirror(receipt) || receipt.mirror?.disposing)) {
console.error("[crabbox] source mirror has no completed idle handoff; using a fresh capsule");
return;
}
if (receipt) {
recoveryMetadata(root, join(root, "payload", "source"));
let intact = false;
try {
intact = Boolean(receipt.mirror?.database) && databaseDigest(root, receipt.witness) === receipt.mirror?.database;
} catch {}
if (!intact) {
assertIdentity(root, receipt.rootIdentity);
rmSync(root, {
recursive: true,
force: true
});
receipt = void 0;
console.error("[crabbox] source mirror metadata changed or disappeared; rebuilding cold");
}
}
}
const reused = Boolean(receipt);
if (!receipt) {
const fresh = createStaging(syncRoot, repository);
if (!fresh.recorded) {
fresh.dispose();
return;
}
root = fresh.root;
receipt = readReceipt(root);
}
if (!root || !canRecordStaging(root, repository)) return;
assertIdentity(join(root, "payload"), receipt.payloadIdentity);
const generations = recoveryMetadata(root, join(root, "payload", "source"));
const adopted = {
...receipt,
ownerPid: process.pid,
ownerDomain: processDomain(),
repository,
repositoryIdentity: identity(repository),
state: "preparing",
users: "none",
claims: void 0,
leases: void 0,
witness: void 0,
artifactManifest: void 0,
mirror: {
key,
slotIdentity,
idle: false,
lastUsed: Date.now()
}
};
saveMirrorReceipt(root, adopted);
if (!writeAtomic(slot, "stage", adopted.id + "\n")) throw new Error("source mirror slot could not be recorded durably");
for (const name of generations) rmSync(join(root, name));
const staging = stagingHandle(root, adopted, true);
const unlock = release;
release = void 0;
let finished = false;
const abandon = () => {
if (!finished) {
unlock();
finished = true;
}
};
const ownedReceipt = () => {
unlock.assertOwned();
const current = mirrorSlot(syncRoot, key);
if (current.root !== root || current.receipt?.ownerPid !== process.pid || current.receipt.mirror?.idle || current.receipt.id !== adopted.id) throw new Error("source mirror ownership changed during its command");
return current.receipt;
};
return {
staging,
reused,
finish() {
if (finished) return;
try {
const current = ownedReceipt();
const idle = {
...current,
mirror: {
...current.mirror,
idle: true,
lastUsed: Date.now()
}
};
if (idleMirror(idle)) {
const source = join(staging.payload, "source");
const outputs = join(source, ".crabbox");
if (lstatSync(outputs, { throwIfNoEntry: false })) try {
const outputIdentity = identity(outputs);
if (!current.artifactManifest) throw new Error("source mirror output preservation was not recorded");
verifyPreservedCrabboxArtifacts(source, readArtifactRecord(staging.root, current.artifactManifest));
unlock.assertOwned();
assertIdentity(outputs, outputIdentity);
if (readdirSync(outputs).some((name) => name !== "runs" && name !== "captures")) {
staging.dispose();
return;
}
idle.mirror.database = databaseDigest(staging.root, current.witness);
for (const name of ["runs", "captures"]) rmSync(join(outputs, name), {
recursive: true,
force: true
});
rmdirSync(outputs);
} catch (error) {
staging.hold("artifacts");
throw error;
}
else idle.mirror.database = databaseDigest(staging.root, current.witness);
saveMirrorReceipt(staging.root, idle);
}
} finally {
abandon();
}
},
discard() {
if (finished) return;
try {
const current = ownedReceipt();
if (current.users !== "none" || current.hold || !["preparing", "prepared"].includes(current.state)) throw new Error("source mirror has admitted or unverified users; retained for recovery");
staging.dispose();
} finally {
abandon();
}
}
};
} catch (error) {
console.error("[crabbox] source mirror unavailable; retained for inspection, using a fresh capsule: " + (error instanceof Error ? error.message : String(error)));
return;
} finally {
release?.();
}
}
function readManifest(root, receipt) {
const bytes = readBounded(join(root, manifestName), manifestLimit);
if (createHash("sha256").update(bytes).digest("hex") !== receipt.manifest) throw new Error("staging manifest does not match its receipt");
try {
return manifestSchema.parse(JSON.parse(bytes.toString("utf8")));
} catch {
throw new Error("staging manifest has unknown or invalid metadata");
}
}
function writeArtifactRecord(root, artifacts, durable = true) {
const bytes = JSON.stringify(artifacts) + "\n";
if (Buffer.byteLength(bytes) > manifestLimit) throw new Error("staging artifact evidence exceeds the recovery metadata limit");
const digest = createHash("sha256").update(bytes).digest("hex");
return {
digest,
durable: writeAtomic(root, "artifacts-" + digest + ".json", bytes, durable)
};
}
function readArtifactRecord(root, digest) {
const bytes = readBounded(join(root, "artifacts-" + digest + ".json"), manifestLimit);
if (createHash("sha256").update(bytes).digest("hex") !== digest) throw new Error("staging artifact evidence does not match its recorded identity");
try {
return crabboxArtifactEvidenceSchema.parse(JSON.parse(bytes.toString("utf8")));
} catch {
throw new Error("staging artifact evidence has unknown or invalid metadata");
}
}
function recoveryMetadata(root, source, artifacts) {
const names = readdirSync(root).toSorted();
if (names.length > 68) throw new Error("staging has too many metadata generations; inspect it before recovery");
const known = /* @__PURE__ */ new Set([
receiptName,
manifestName,
"payload",
"recovery.lock"
]);
const sourceIdentity = lstatSync(source, { throwIfNoEntry: false }) ? identity(source) : artifacts?.sourceIdentity;
const generations = [];
const mirror = readReceipt(root).mirror;
for (const name of names) {
if (known.has(name)) continue;
if (mirror && [
mirrorDatabase,
`${mirrorDatabase}-journal`,
`${mirrorDatabase}-wal`,
`${mirrorDatabase}-shm`
].includes(name)) {
const stat = lstatSync(join(root, name));
if (!stat.isFile() && !stat.isSymbolicLink()) throw new Error("source mirror database metadata has an unsupported kind");
continue;
}
const match = /^artifacts-([a-f0-9]{64})\.json$/u.exec(name);
if (!match || !sourceIdentity || !sameIdentity(readArtifactRecord(root, match[1]).sourceIdentity, sourceIdentity)) throw new Error("staging has an unknown or replaced metadata sibling; preserve it before recovery");
generations.push(name);
}
return generations;
}
function metadataStatus(root, receipt, explicit = false) {
const base = {
id: receipt.id,
directory: root,
ownerPid: receipt.ownerPid,
state: receipt.state,
users: receipt.users,
kind: receipt.kind,
hold: receipt.hold,
leases: receipt.leases
};
if (lstatSync(join(root, "recovery.lock"), { throwIfNoEntry: false })) return {
...base,
status: "protected",
reason: "Another or interrupted recovery owns this copy; inspect that operation before manual disposition."
};
if (idleMirror(receipt)) return {
...base,
status: receipt.mirror?.disposing ? "candidate" : "protected",
reason: receipt.mirror?.disposing ? "Interrupted idle source mirror disposal; its exclusive slot lock must be acquired before resuming." : "Idle source mirror retained for reuse; capacity eviction or explicit staging recover uses its exclusive mirror lock."
};
if (!receipt.ownerDomain || receipt.ownerDomain !== processDomain()) return {
...base,
status: "protected",
reason: "The producer belongs to an unknown or different boot/process namespace; this process cannot establish its absence."
};
if (!ownerAbsent(receipt.ownerPid)) return {
...base,
status: "active",
reason: "The producer PID is live or cannot be checked; wait for its cleanup."
};
if (receipt.kind === "worktree") return {
...base,
status: "protected",
reason: "Full-worktree preparation can run hooks or filters. Preserve its raw source and outputs, then verify this exact Git registration before manual disposition; recovery does not adopt it."
};
if (!receipt.durable || !receipt.manifest) return {
...base,
status: "protected",
reason: "Preparation or durable recovery metadata is incomplete; preserve this copy for inspection."
};
if (receipt.users === "admitted" || receipt.state === "preparing") return {
...base,
status: "protected",
reason: "Writer settlement was not recorded; PID absence does not authorize removal."
};
if (receipt.hold === "writers" || receipt.hold === "registration") return {
...base,
status: "protected",
reason: "Writer or registration settlement is unverified; inspect and preserve this copy before manual disposition."
};
if (!explicit && (receipt.hold || receipt.users === "settled" && receipt.state === "settled")) return {
...base,
status: "protected",
reason: "Claim or diagnostic preservation is incomplete; repair the named destination or lease, then run staging recover with this ID to retry."
};
if (![
"prepared",
"settled",
"preserved",
"removing"
].includes(receipt.state)) return {
...base,
status: "protected",
reason: "Staging state is inconsistent with recorded ownership; preserve it for inspection."
};
if (!receipt.claims) return {
...base,
status: "protected",
reason: "The original native claims namespace was not recorded; absence in another namespace cannot authorize removal."
};
if (!receipt.witness) return {
...base,
status: "protected",
reason: "No independent retained Git ref is recorded; preserve the snapshot in a retained repository first."
};
return {
...base,
status: "candidate",
reason: "Source preservation and unchanged contents must still be verified before removal."
};
}
function inspectStaging(syncRoot, options = {}) {
const started = performance.now();
const entries = [];
let incomplete = false;
let nextCursor = options.startAfter;
let skipping = Boolean(options.startAfter);
let directory;
try {
directory = opendirSync(syncRoot);
} catch (error) {
if (error.code === "ENOENT") return {
entries,
incomplete,
nextCursor: void 0,
elapsedMs: performance.now() - started
};
throw error;
}
try {
for (;;) {
if (entries.length >= (options.limit ?? 64) || performance.now() - started >= (options.budgetMs ?? 250)) {
incomplete = true;
break;
}
const entry = directory.readSync();
if (!entry) {
nextCursor = void 0;
incomplete = skipping;
break;
}
if (skipping) {
skipping = entry.name !== options.startAfter;
continue;
}
if (!entry.name.startsWith(prefix) || entry.name === cursorName) continue;
nextCursor = entry.name;
const root = join(syncRoot, entry.name);
try {
const disposalId = entry.name.startsWith(prefix + "disposal-") ? entry.name.slice(31) : void 0;
const disposal = disposalId ? readDisposal(syncRoot, disposalId) : void 0;
const receipt = disposal ? disposal.receipt : readMirrorState(syncRoot, entry.name.slice(22)).receipt;
if (!receipt && !disposal) throw new Error("staging has no recorded owner");
const id = disposal?.id ?? receipt.id;
if (!entries.some((value) => value.id === id)) entries.push(receipt ? {
...metadataStatus(join(syncRoot, prefix + id), receipt),
directory: root
} : {
id,
directory: root,
status: "candidate",
reason: "Recorded empty source mirror slot disposal; its allocation and slot locks must be acquired before resuming."
});
} catch {
entries.push({
id: entry.name,
directory: root,
status: "protected",
reason: "Unmarked, unknown, replaced or unreadable staging; no automatic adoption."
});
}
}
} finally {
directory.closeSync();
}
return {
entries,
incomplete,
nextCursor,
elapsedMs: performance.now() - started
};
}
const cursorSchema = strictObject({
version: literal(1),
rootIdentity: identitySchema,
cursorIdentity: identitySchema,
after: string().startsWith(prefix).max(256).optional()
});
function readCursor(syncRoot) {
const physicalRoot = realpathSync(syncRoot);
const root = join(physicalRoot, cursorName);
const value = cursorSchema.parse(JSON.parse(readBounded(join(root, "position.json"), headerLimit).toString("utf8")));
assertIdentity(physicalRoot, value.rootIdentity);
assertIdentity(root, value.cursorIdentity);
if (value.after && basename(value.after) !== value.after) throw new Error("staging discovery cursor is invalid");
return value;
}
/** Metadata-only discovery; its cursor is a fairness hint, never deletion authority. */
function discoverStaging(syncRoot) {
let startAfter;
try {
startAfter = readCursor(syncRoot).after;
} catch {}
return inspectStaging(syncRoot, { startAfter });
}
/** Advance bounded discovery and attempt at most one old candidate after normal completion. */
async function recoverDiscoveredStaging(syncRoot, discovery, options) {
options.signal?.throwIfAborted();
if (!discovery.entries.length && !discovery.incomplete) return;
const physicalRoot = realpathSync(syncRoot);
const cursor = join(physicalRoot, cursorName);
const candidate = discovery.entries.find((entry) => entry.status === "candidate");
try {
if (!canRecordStaging(cursor, options.cwd)) throw new Error("This source location does not support recovery metadata.");
if (!lstatSync(cursor, { throwIfNoEntry: false })) mkdirSync(cursor, { mode: 448 });
else readCursor(physicalRoot);
writeAtomic(cursor, "position.json", JSON.stringify({
version: 1,
rootIdentity: identity(physicalRoot),
cursorIdentity: identity(cursor),
after: candidate ? basename(candidate.directory) : discovery.nextCursor
}) + "\n");
} catch {
options.signal?.throwIfAborted();
console.error("[crabbox] staging discovery cursor is unavailable; retained it for inspection. Use staging inspect --after to page past protected entries.");
}
if (candidate) return recoverStaging(physicalRoot, candidate.id, {
...options,
automatic: true
});
}
function validatePayload(root, receipt, manifest) {
const payload = join(root, "payload");
if (!lstatSync(payload, { throwIfNoEntry: false }) && receipt.state === "removing") return "[]";
assertIdentity(payload, receipt.payloadIdentity);
const entries = manifest.artifacts ? manifest.entries.filter((entry) => !artifactPath(entry.path)) : manifest.entries;
const expected = new Map(entries.map((entry) => [entry.path, entry]));
if (expected.size !== entries.length || [...expected.keys()].some((path) => !safeRelative(path))) throw new Error("staging manifest contains duplicate or unsafe paths");
const actual = inventory(payload, /* @__PURE__ */ new Map(), Boolean(manifest.artifacts));
for (const entry of actual) {
const frozen = expected.get(entry.path);
if (!frozen || frozen.kind !== entry.kind || frozen.mode !== entry.mode || frozen.blob !== entry.blob) throw new Error("staging contents changed or gained an entry: " + entry.path);
expected.delete(entry.path);
}
if (expected.size && receipt.state !== "removing") throw new Error("staging contents are missing before disposal");
return JSON.stringify(actual);
}
async function recoverStaging(syncRoot, id, options) {
if (!uuid().safeParse(id).success) return {
id,
recovered: false,
reason: "Choose a recorded staging ID from staging inspect."
};
const root = join(syncRoot, prefix + id);
const source = join(root, "payload", "source");
let locked = false;
let unsettled = false;
let releaseMirror;
let lockedRoot;
let lockedDirectory;
const lockOwner = JSON.stringify({
pid: process.pid,
generation: randomUUID()
}) + "\n";
const lock = join(root, "recovery.lock");
try {
options.signal?.throwIfAborted();
const { receipt: before, disposal: recordedDisposal } = readMirrorState(syncRoot, id);
if (recordedDisposal || before && idleMirror(before)) {
const key = recordedDisposal?.key ?? before.mirror.key;
const slotIdentity = recordedDisposal?.slotIdentity ?? before.mirror.slotIdentity;
if (options.automatic && !recordedDisposal && !before?.mirror?.disposing) return {
id,
recovered: false,
reason: "Idle source mirrors are retained until capacity eviction or explicit recovery."
};
let allocation = mirrorLock(join(syncRoot, "mirrors", ".allocation.lock"), true);
if (!allocation) return {
id,
recovered: false,
reason: "Source mirror allocation is busy; retry after the active command finishes."
};
let victim;
try {
const slot = join(syncRoot, "mirrors", key);
if (recordedDisposal && !lstatSync(root, { throwIfNoEntry: false })) {
const current = lstatSync(slot, { throwIfNoEntry: false }) ? mirrorSlot(syncRoot, key, id) : void 0;
if (!current || current.receipt && current.id !== id) {
removeDisposal(syncRoot, recordedDisposal);
return {
id,
recovered: true,
reason: "Completed source mirror disposal record removed."
};
}
if (!sameIdentity(current.slotIdentity, slotIdentity)) throw new Error("Source mirror disposal slot identity changed.");
}
victim = claimIdleMirror(syncRoot, key, id);
allocation();
allocation = void 0;
if (victim) {
victim.removePayload();
allocation = mirrorLock(join(syncRoot, "mirrors", ".allocation.lock"), true);
if (!allocation) throw new Error("Source mirror allocation is busy; recorded disposal retained for recovery.");
victim.removeSlot();
}
const recovered = Boolean(victim);
return {
id,
recovered,
reason: recovered ? "Explicitly disposable idle source mirror removed." : "Source mirror is in use or its ownership changed; retained."
};
} finally {
victim?.release();
allocation?.();
}
}
if (!before) throw new Error("Staging has no recorded owner.");
const selectedWitness = options.witness ?? before.witness;
const status = metadataStatus(root, {
...before,
witness: selectedWitness
}, !options.automatic);
if (status.status !== "candidate") return {
id,
recovered: false,
reason: status.reason
};
if (before.mirror) {
const allocation = mirrorLock(join(syncRoot, "mirrors", ".allocation.lock"), true);
if (!allocation) return {
id,
recovered: false,
reason: "Source mirror allocation is busy; retry after the active command finishes."
};
try {
const slot = mirrorSlot(syncRoot, before.mirror.key);
if (slot.root !== root) throw new Error("Source mirror staging ownership changed before recovery.");
releaseMirror = mirrorLock(join(slot.slot, "lock"));
if (!releaseMirror) return {
id,
recovered: false,
reason: "Source mirror has an active lock owner; retained."
};
} finally {
allocation();
}
}
mkdirSync(lock, { mode: 448 });
locked = true;
lockedRoot = identity(root);
lockedDirectory = identity(lock);
writeFileSync(join(lock, "owner.json"), lockOwner, {
mode: 384,
flag: "wx"
});
let receipt = readReceipt(root);
if (JSON.stringify(receipt) !== JSON.stringify(before) || !ownerAbsent(receipt.ownerPid)) throw new Error("staging ownership changed while acquiring recovery");
const saveReceipt = (next) => {
assertIdentity(root, receipt.rootIdentity);
receipt = next;
if (!writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n")) {
receipt.durable = false;
writeAtomic(root, receiptName, JSON.stringify(receipt) + "\n", false);
throw new Error("Durable recovery updates are unavailable; staging remains protected.");
}
};
const checkClaims = async () => {
const claims = await verifyNoStagingClaims({
binary: options.binary,
cwd: options.cwd,
namespace: receipt.claims,
sourceRoot: root,
signal: options.signal
});
if (!claims.ok) {
unsettled ||= claims.unjoined === true;
if (!unsettled) saveReceipt({
...receipt,
hold: "claims",
leases: claims.matchingLeaseIds ?? receipt.leases
});
throw new Error(claims.reason + (claims.matchingLeaseIds?.length ? " Matching leases: " + JSON.stringify(claims.matchingLeaseIds) : ""), { cause: claims.error });
}
};
await checkClaims();
let manifest = readManifest(root, receipt);
if (receipt.artifactManifest) manifest = {
...manifest,
artifacts: readArtifactRecord(root, receipt.artifactManifest)
};
recoveryMetadata(root, source, manifest.artifacts);
if (receipt.users === "settled") try {
if (!manifest.artifacts) throw new Error("Diagnostic preservation was not recorded.");
verifyPreservedCrabboxArtifacts(source, manifest.artifacts, receipt.state === "removing");
} catch (error) {
if (options.automatic || receipt.state === "removing") throw error;
if (!receipt.repositoryIdentity) throw new Error("Original repository identity is unavailable; preserve diagnostics manually.", { cause: error });
const artifacts = preserveCrabboxArtifacts(source, receipt.repository, receipt.repositoryIdentity);
if (!artifacts?.durable) throw new Error("Durable diagnostic preservation could not be established.", { cause: error });
manifest = {
...manifest,
artifacts
};
const saved = writeArtifactRecord(root, artifacts);
if (!saved.durable) throw new Error("Durable artifact evidence could not be recorded.", { cause: error });
saveReceipt({
...receipt,
artifactManifest: saved.digest,
state: "preserved",
hold: void 0
});
}
const generations = recoveryMetadata(root, source, manifest.artifacts);
const footprint = validatePayload(root, receipt, manifest);
const witness = await verifySourceWitness({
source: manifest.source,
witness: selectedWitness,
payloadRoot: root,
automatic: options.automatic,
signal: options.signal
});
if (!witness.ok) {
unsettled ||= witness.unjoined === true;
return {
id,
recovered: false,
reason: witness.reason
};
}
await checkClaims();
options.signal?.throwIfAborted();
if (JSON.stringify(readReceipt(root)) !== JSON.stringify(receipt) || !ownerAbsent(receipt.ownerPid)) throw new Error("staging ownership changed during preservation verification");
if (validatePayload(root, receipt, manifest) !== footprint) throw new Error("staging changed during preservation verification");
if (manifest.artifacts) verifyPreservedCrabboxArtifacts(source, manifest.artifacts, receipt.state === "removing");
assertIdentity(lock, lockedDirectory);
if (readBounded(join(lock, "owner.json"), headerLimit).toString("utf8") !== lockOwner || JSON.stringify(recoveryMetadata(root, source, manifest.artifacts)) !== JSON.stringify(generations)) throw new Error("staging metadata changed during preservation verification");
saveReceipt({
...receipt,
state: "removing",
hold: void 0,
witness: selectedWitness
});
witness.revalidate();
rmSync(join(root, "payload"), {
recursive: true,
force: true
});
rmSync(join(root, manifestName));
for (const name of generations) rmSync(join(root, name));
if (receipt.mirror) for (const name of [
mirrorDatabase,
`${mirrorDatabase}-journal`,
`${mirrorDatabase}-wal`,
`${mirrorDatabase}-shm`
]) rmSync(join(root, name), { force: true });
rmSync(join(root, receiptName));
rmSync(join(lock, "owner.json"));
rmdirSync(lock);
locked = false;
rmdirSync(root);
return {
id,
recovered: true,
reason: "Independent retained source, diagnostics, and native claims verified; abandoned staging removed."
};
} catch (error) {
return {
id,
recovered: false,
reason: error.code === "EEXIST" ? "Another or interrupted recovery owns this copy; inspect its owner before manual disposition." : error instanceof Error ? error.message : "Staging recovery could not be verified."
};
} finally {
if (locked && !unsettled && lockedRoot && lockedDirectory) try {
assertIdentity(root, lockedRoot);
assertIdentity(lock, lockedDirectory);
if (readBounded(join(lock, "owner.json"), headerLimit).toString("utf8") === lockOwner) {
rmSync(join(lock, "owner.json"));
rmdirSync(lock);
}
} catch {}
if (!unsettled) releaseMirror?.();
}
}
async function runStagingCommand(args, syncRoot, options) {
if (args[0] === "inspect" && (args.length === 1 || args.length === 3 && args[1] === "--after" && args[2].startsWith(prefix) && basename(args[2]) === args[2])) {
console.log(JSON.stringify(inspectStaging(syncRoot, { startAfter: args[2] }), null, 2));
return 0;
}
if (args[0] === "recover" && (args.length === 2 || args.length === 6)) try {
let witness;
if (args.length === 6) {
const fields = /* @__PURE__ */ new Map([[args[2], args[3]], [args[4], args[5]]]);
if (fields.size !== 2 || !fields.get("--witness-repo") || !fields.get("--witness-ref")) throw new Error("Supply both --witness-repo and --witness-ref, with one value each.");
witness = selectSourceWitness(fields.get("--witness-repo"), fields.get("--witness-ref"));
}
const result = await recoverStaging(syncRoot, args[1], {
...options,
witness
});
console.log(JSON.stringify(result, null, 2));
return result.recovered ? 0 : 1;
} catch (error) {
console.log(JSON.stringify({
id: args[1],
recovered: false,
reason: error instanceof Error ? error.message : "Recovery options could not be verified."
}, null, 2));
return 1;
}
console.log("Usage: node scripts/crabbox-wrapper.mjs staging inspect [--after <nextCursor>]\n node scripts/crabbox-wrapper.mjs staging recover <id> [--witness-repo <path> --witness-ref <full-ref>]\n\nOnly positively settled, unchanged staging with independently retained source and preserved diagnostics can be removed. Existing native claims are inspected without provider calls or claim mutation.");
return args.length === 0 || args[0] === "--help" ? 0 : 2;
}
//#endregion
export { runStagingCommand as a, captureSourceWitness as c, recoverDiscoveredStaging as i, createStaging as n, captureClaimNamespace as o, discoverStaging as r, preserveCrabboxArtifacts as s, createMirrorStaging as t };