feat: harden self-managed reconciliation

This commit is contained in:
2026-09-05 10:17:55 +00:00 Unverified
parent 8e9d207915
commit 321f4e807a
40 changed files with 4977 additions and 404 deletions
+26 -8
View File
@@ -27,7 +27,30 @@ import {
export interface MaterializeCas {
get(digest: Sha256Digest): Promise<Uint8Array>;
has(digest: Sha256Digest): Promise<boolean>;
}
const MATERIALIZE_CONCURRENCY = 20;
async function mapConcurrent<T, R>(
values: T[],
run: (value: T) => Promise<R>,
): Promise<R[]> {
const results = new Array<R>(values.length);
let index = 0;
const worker = async () => {
for (;;) {
const current = index++;
if (current >= values.length) return;
results[current] = await run(values[current]!);
}
};
await Promise.all(
Array.from(
{ length: Math.min(MATERIALIZE_CONCURRENCY, values.length) },
worker,
),
);
return results;
}
function safePath(path: string): boolean {
@@ -105,11 +128,6 @@ export async function materializeWorkspace(
): Promise<WorkspaceManifest> {
assertSha256Digest(manifestDigest);
const manifest = parseWorkspaceManifest(await cas.get(manifestDigest));
const missing: Sha256Digest[] = [];
for (const file of manifest.files)
if (!(await cas.has(file.digest))) missing.push(file.digest);
if (missing.length)
throw new Error(`Workspace blobs are missing: ${missing.join(", ")}`);
await mkdir(dirname(destination), { recursive: true });
try {
@@ -124,7 +142,7 @@ export async function materializeWorkspace(
);
await mkdir(temporary, { mode: 0o755 });
try {
for (const file of manifest.files) {
await mapConcurrent(manifest.files, async (file) => {
const target = join(temporary, file.path);
if (relative(temporary, target).startsWith(".."))
throw new Error("Unsafe workspace path");
@@ -151,7 +169,7 @@ export async function materializeWorkspace(
}
await chmod(target, file.mode);
}
}
});
await rename(temporary, destination);
} catch (error) {
await rm(temporary, { recursive: true, force: true });