Materialize independent files in new provider packs

Bind the new layout policy into provider-pack identity and verify it on controller and guest while preserving legacy immutable packs and approved image root aliases.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-11 08:34:25 -05:00
1 parent f5a393dd60
commit b64d630969
10 files changed
+235

No files matched your search

+9
View File
@@ -168,6 +168,15 @@ are unavailable. Accepting a native plan ends the planning run successfully whil
the task waits for the next instruction. See the
[Cursor release report](../../doc/plans/2026-10-03-cursor-production-readiness.md).
New provider packs declare `payload.fileLayout: "independent-regular-files-v1"`.
The builder separates hardlinked regular files in its unpublished temporary tree,
preserving file bytes, modes, and symlinks. The policy participates in the manifest
digest, so a new layout cannot reuse a legacy cache identity. Controller and guest
verification reject unknown policies and hardlinked files under this policy.
Existing manifests without the field retain their original immutable contract;
they are not rewritten or repaired during session reuse. Runtime module and
executable integrity guards remain unchanged.
A release includes all three platform daemons and the Linux provider-pack identity
from its matching Daytona image. Run `stage:release-binaries` with a manifest that
binds each daemon path and SHA-256, plus `remoteProviderPack: {path, sha256}` for
@@ -20,6 +20,7 @@ import { dirname, join, relative, resolve } from "node:path";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import { parseProviderPackArguments, materializeCandidateProviderPack, providerPackProviders, providerPackManifestFields } from "./candidate-provider-pack.mjs";
import { materializeIndependentProviderPackFiles, PROVIDER_PACK_FILE_LAYOUT } from "./provider-pack-file-layout.mjs";
import { buildNodeStartupTimeout } from "./build-node-startup-timeout.mjs";
import { writePortableExecutableShim, writePortableCopilotShims } from "./provider-pack-executable-shims.mjs";
@@ -277,6 +278,8 @@ try {
}
}
materializeIndependentProviderPackFiles(temporaryRoot);
const opencodeProxySha = sha256File(join(temporaryRoot, opencodeProxyPath));
const acpxSidecarSha = sha256File(join(temporaryRoot, acpxSidecarPath));
const distDigest = sha256Tree(join(temporaryRoot, "dist"));
@@ -297,6 +300,7 @@ try {
cwd: workspaceRoot,
}).status !== 0;
const payload = {
fileLayout: PROVIDER_PACK_FILE_LAYOUT,
pins: {
nodeMinimum: minimumNodeVersion.join("."),
codex: profiles.profiles.codex.agentRuntimeVersion,
@@ -0,0 +1,43 @@
import { chmodSync, constants, copyFileSync, lstatSync, mkdtempSync, readdirSync, renameSync, rmSync, utimesSync } from "node:fs";
import { join } from "node:path";
export const PROVIDER_PACK_FILE_LAYOUT = "independent-regular-files-v1";
/** Only call on the unpublished build tree, never on a retained provider cache. */
export function materializeIndependentProviderPackFiles(root) {
const visit = directory => {
for (const name of readdirSync(directory)) {
const file = join(directory, name);
const stat = lstatSync(file);
if (stat.isDirectory()) visit(file);
else if (stat.isSymbolicLink()) continue;
else if (!stat.isFile()) throw new Error("Unsupported provider pack file layout entry");
else if (stat.nlink > 1) {
// Copy to a new inode before changing metadata: the source may also be
// linked into pnpm's store outside this unpublished tree.
const temporary = mkdtempSync(join(directory, ".paperclip-independent-"));
try {
const replacement = join(temporary, "file");
copyFileSync(file, replacement, constants.COPYFILE_EXCL);
chmodSync(replacement, stat.mode & 0o7777);
utimesSync(replacement, stat.atimeMs / 1000, stat.mtimeMs / 1000);
renameSync(replacement, file);
} finally {
rmSync(temporary, { recursive: true, force: true });
}
}
}
};
if (!lstatSync(root).isDirectory()) throw new Error("Invalid provider pack build root");
visit(root);
const verify = directory => {
for (const name of readdirSync(directory)) {
const file = join(directory, name);
const stat = lstatSync(file);
if (stat.isDirectory()) verify(file);
else if (stat.isFile() && stat.nlink !== 1) throw new Error("Provider pack files are not independent");
else if (!stat.isFile() && !stat.isSymbolicLink()) throw new Error("Unsupported provider pack file layout entry");
}
};
verify(root);
}
@@ -0,0 +1,61 @@
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import { chmodSync, linkSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { materializeIndependentProviderPackFiles } from "./provider-pack-file-layout.mjs";
test("new pack files remain independent after a real tar round trip without changing source bytes, modes or symlinks", () => {
const root = mkdtempSync(join(tmpdir(), "provider-pack-layout-"));
try {
const pack = join(root, "pack"); mkdirSync(pack);
const outside = join(root, "store"); mkdirSync(outside);
const source = join(outside, "source"); writeFileSync(source, "identical module bytes\n"); chmodSync(source, 0o755);
linkSync(source, join(pack, "a")); linkSync(source, join(pack, "b"));
writeFileSync(join(pack, "c"), "identical module bytes\n");
symlinkSync("a", join(pack, "relative-link"));
symlinkSync(outside, join(pack, "external-directory-link"));
writeFileSync(join(outside, "untouched-a"), "outside");
linkSync(join(outside, "untouched-a"), join(outside, "untouched-b"));
const outsideInode = lstatSync(join(outside, "untouched-a")).ino;
const original = lstatSync(source);
// Prove plain tar preserves the old hardlink topology.
execFileSync("tar", ["-czf", join(root, "legacy.tgz"), "-C", pack, "."]);
const legacy = join(root, "legacy"); mkdirSync(legacy);
execFileSync("tar", ["-xzf", join(root, "legacy.tgz"), "-C", legacy]);
assert.equal(lstatSync(join(legacy, "a")).ino, lstatSync(join(legacy, "b")).ino);
assert.equal(lstatSync(join(legacy, "a")).nlink, 2);
materializeIndependentProviderPackFiles(pack);
const once = ["a", "b", "c"].map(name => lstatSync(join(pack, name)).ino);
materializeIndependentProviderPackFiles(pack);
assert.deepEqual(["a", "b", "c"].map(name => lstatSync(join(pack, name)).ino), once);
execFileSync("tar", ["-czf", join(root, "independent.tgz"), "-C", pack, "."]);
const unpacked = join(root, "unpacked"); mkdirSync(unpacked);
execFileSync("tar", ["-xzf", join(root, "independent.tgz"), "-C", unpacked]);
const stats = ["a", "b", "c"].map(name => lstatSync(join(unpacked, name)));
assert.equal(new Set(stats.map(stat => stat.ino)).size, 3);
assert.ok(stats.every(stat => stat.nlink === 1));
for (const name of ["a", "b", "c"]) assert.equal(readFileSync(join(unpacked, name), "utf8"), "identical module bytes\n");
assert.equal(stats[0].mode & 0o7777, 0o755);
assert.equal(stats[1].mode & 0o7777, 0o755);
assert.equal(readlinkSync(join(unpacked, "relative-link")), "a");
assert.equal(readlinkSync(join(unpacked, "external-directory-link")), outside);
const after = lstatSync(source);
assert.equal(after.ino, original.ino); assert.equal(after.mode, original.mode);
assert.equal(after.mtimeMs, original.mtimeMs); assert.equal(after.nlink, 1);
assert.equal(readFileSync(source, "utf8"), "identical module bytes\n");
for (const name of ["untouched-a", "untouched-b"]) {
assert.equal(lstatSync(join(outside, name)).ino, outsideInode);
assert.equal(lstatSync(join(outside, name)).nlink, 2);
}
} finally { rmSync(root, { recursive: true, force: true }); }
});
test("does not accept a symlink as the unpublished root", () => {
const root = mkdtempSync(join(tmpdir(), "provider-pack-layout-root-"));
try {
mkdirSync(join(root, "tree")); symlinkSync(join(root, "tree"), join(root, "link"));
assert.throws(() => materializeIndependentProviderPackFiles(join(root, "link")), /build root/);
} finally { rmSync(root, { recursive: true, force: true }); }
});
@@ -12,6 +12,9 @@ export function verifyReleaseProviderPack(identity, sourceRevision) {
if (identity?.schema !== "paperclip-runner/remote-provider-pack/v1" || !payload
|| payload.target?.platform !== "linux" || payload.target?.architecture !== "x64"
|| payload.runnerSourceRevision !== sourceRevision) throw new Error("Remote provider pack must match the release source and Linux x64 target");
if (payload.fileLayout !== undefined && payload.fileLayout !== "independent-regular-files-v1") {
throw new Error("Remote provider-pack file layout is unsupported");
}
if (identity.digest !== `sha256:${createHash("sha256").update(canonical(payload)).digest("hex")}`) {
throw new Error("Remote provider-pack payload digest mismatch");
}
@@ -77,3 +77,14 @@ test("release assembly rejects rehashed stale or missing packs before staging an
}
} finally { rmSync(root, { recursive: true, force: true }); }
});
test("file layout is a closed, digest-bound policy with legacy compatibility", () => {
const legacy = seal(fixture());
const independent = seal({ ...fixture(), fileLayout: "independent-regular-files-v1" });
assert.notEqual(independent.digest, legacy.digest);
assert.equal(verifyReleaseProviderPack(independent, revision), independent);
assert.equal(verifyReleaseProviderPack(legacy, revision), legacy);
for (const fileLayout of [null, {}, "unknown-policy"]) {
assert.throws(() => verifyReleaseProviderPack(seal({ ...fixture(), fileLayout }), revision), /file layout/);
}
});
@@ -8,6 +8,7 @@ import {
chmod,
cp,
lstat,
link,
mkdir,
mkdtemp,
open,
@@ -1289,6 +1290,28 @@ describe("remote provider pack manifest", () => {
expect(readRemoteProviderPackManifest(root).payload.pins.opencode).toBe(
"1.18.34",
);
// Content digests cannot distinguish hardlinks from independent files.
const legacyDigest = readRemoteProviderPackManifest(root).digest;
const alias = join(root, "node_modules", "node-alias");
await link(join(root, "node_modules", "node", "bin", "node"), alias);
expect(readRemoteProviderPackManifest(root).digest).toBe(legacyDigest);
Object.assign(payload, { fileLayout: "independent-regular-files-v1" });
await writeManifest();
expect(() => readRemoteProviderPackManifest(root)).toThrow("provider pack file layout");
expect((await lstat(alias)).nlink).toBe(2); // Reject; never repair immutable caches.
await rm(alias);
const independent = readRemoteProviderPackManifest(root);
expect(independent.digest).not.toBe(legacyDigest);
expect(readBundledRemoteProviderPackManifest(join(root, "provider-pack.json")).digest).toBe(independent.digest);
expect(independent.payload.distDigest).toBe(payload.distDigest);
expect(readRemoteProviderPackManifest(root).digest).toBe(independent.digest);
Object.assign(payload, { fileLayout: "unknown-policy" });
await writeManifest();
expect(() => readRemoteProviderPackManifest(root)).toThrow("provider pack file layout");
expect(() => readBundledRemoteProviderPackManifest(join(root, "provider-pack.json"))).toThrow("provider pack file layout");
delete (payload as typeof payload & { fileLayout?: string }).fileLayout;
await writeManifest();
expect(readRemoteProviderPackManifest(root).digest).toBe(legacyDigest);
const cursorPath = "provider-assets/cursor/linux-x64";
await mkdir(join(root, cursorPath), { recursive: true });
await writeFile(join(root, cursorPath, "runtime"), "pinned Cursor runtime");
@@ -38,6 +38,7 @@ import {
import { nativeCompletionFeedback } from "./native-completion-feedback.js";
import { hasAcknowledgedNativeReassignmentStopIntent, hasAcknowledgedNativeStopIntent } from "../acknowledged-native-stop.js";
import { stoppedCodexTurnIsTextOnly } from "./stopped-codex-turn.js";
import { verifyProviderPackFileLayout } from "./remote-provider-pack-file-layout.js";
import { prepareVerifiedRemoteProviderPack } from "./remote-provider-pack.js";
import { selectRemotePiCompanion } from "./remote-pi-companion.js";
import { readNativeLocalProcessStop, PROCESS_START_REQUESTED } from "../native-local-process-stop.js";
@@ -67,6 +68,7 @@ import {
readSync,
renameSync,
rmSync,
statSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
@@ -9906,6 +9908,7 @@ type RemoteProviderPackManifest = {
schema: typeof REMOTE_PROVIDER_PACK_SCHEMA;
digest: string;
payload: {
fileLayout?: "independent-regular-files-v1";
pins: typeof REMOTE_PROVIDER_PACK_PINS;
target: { platform: string; architecture: string };
runnerSourceRevision: string;
@@ -10029,6 +10032,7 @@ function readRemoteProviderPackIdentity(packRoot: string, verifyControllerFiles:
"runner_remote_provider_artifact_incompatible: provider pack pins or source revision do not match",
);
}
verifyProviderPackFileLayout(null, payload.fileLayout, { lstatSync, statSync, readdirSync }, { join });
const digest = `sha256:${createHash("sha256")
.update(canonicalJson(payload))
.digest("hex")}`;
@@ -10139,6 +10143,9 @@ function readRemoteProviderPackIdentity(packRoot: string, verifyControllerFiles:
"runner_remote_provider_artifact_incompatible: provider bridge digest mismatch",
);
}
if (verifyControllerFiles) {
verifyProviderPackFileLayout(packRoot, payload.fileLayout, { lstatSync, statSync, readdirSync }, { join });
}
return structuredClone(manifest);
}
@@ -11745,6 +11752,7 @@ async function createRunnerdBackendWithinSessionClaim(
"const packageVersion=(pkg)=>JSON.parse(fs.readFileSync(path.join(root,'node_modules',...pkg.split('/'),'package.json'),'utf8')).version",
"const expectedPackages={acpx:manifest.payload.pins.acpx,'@agentclientprotocol/claude-agent-acp':manifest.payload.pins.claudeAcp,'@agentclientprotocol/codex-acp':manifest.payload.pins.codexAcp,'opencode-ai':manifest.payload.pins.opencode}",
"for(const [pkg,version] of Object.entries(expectedPackages))if(packageVersion(pkg)!==version)throw new Error(pkg+' version mismatch')",
`(${verifyProviderPackFileLayout.toString()})(root,manifest.payload.fileLayout,fs,path)`,
].join(";");
const verified = await remoteCommandRunner.execute({
command: providerNodeCommand,
@@ -0,0 +1,48 @@
import { afterEach, describe, expect, it } from "vitest";
import * as fs from "node:fs";
import * as path from "node:path";
import { tmpdir } from "node:os";
import { execFileSync } from "node:child_process";
import { verifyProviderPackFileLayout } from "./remote-provider-pack-file-layout.js";
const roots: string[] = [];
afterEach(() => { for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true }); });
function fixture() {
const root = fs.mkdtempSync(path.join(tmpdir(), "remote-file-layout-")); roots.push(root);
fs.mkdirSync(path.join(root, "nested")); fs.writeFileSync(path.join(root, "nested", "one"), "same bytes");
fs.symlinkSync("nested/one", path.join(root, "link"));
return root;
}
function check(root: string, policy: unknown, remote: boolean) {
if (!remote) return verifyProviderPackFileLayout(root, policy, fs, path);
// Exercise precisely the self-contained function serialized by the guest verifier.
const program = `const fs=require('node:fs'),path=require('node:path');(${verifyProviderPackFileLayout.toString()})(process.argv[1],JSON.parse(process.argv[2]).policy,fs,path)`;
execFileSync(process.execPath, ["-e", program, root, JSON.stringify({ policy })], { stdio: "pipe" });
}
describe.each([false, true])("provider file layout validation remote=%s", remote => {
it("accepts independent files and symlinks; rejects later hardlinks without repair", () => {
const root = fixture(); const policy = "independent-regular-files-v1";
check(root, policy, remote);
fs.linkSync(path.join(root, "nested", "one"), path.join(root, "two"));
expect(() => check(root, policy, remote)).toThrow("runner_remote_provider_artifact_incompatible: provider pack file layout");
expect(fs.lstatSync(path.join(root, "two")).nlink).toBe(2);
check(root, undefined, remote); // Legacy caches remain readable and unchanged.
expect(fs.lstatSync(path.join(root, "two")).nlink).toBe(2);
});
it("accepts an authority-selected preinstalled root alias without following interior directory aliases", () => {
const root = fixture();
const aliasParent = fs.mkdtempSync(path.join(tmpdir(), "preinstalled-file-layout-")); roots.push(aliasParent);
const alias = path.join(aliasParent, "approved-image-pack"); fs.symlinkSync(root, alias);
const outside = path.join(aliasParent, "outside"); fs.mkdirSync(outside);
fs.writeFileSync(path.join(outside, "one"), "unrelated");
fs.linkSync(path.join(outside, "one"), path.join(outside, "two"));
fs.symlinkSync(outside, path.join(root, "interior-directory-alias"));
check(alias, "independent-regular-files-v1", remote);
expect(fs.lstatSync(path.join(outside, "one")).nlink).toBe(2);
fs.linkSync(path.join(root, "nested", "one"), path.join(root, "two"));
expect(() => check(alias, "independent-regular-files-v1", remote)).toThrow("runner_remote_provider_artifact_incompatible: provider pack file layout");
});
it.each([null, "unknown-policy", {}, 1])("rejects unknown policy %j", policy => {
expect(() => check(fixture(), policy, remote)).toThrow("runner_remote_provider_artifact_incompatible: provider pack file layout");
});
});
@@ -0,0 +1,25 @@
/** Also serialized into the remote verifier; keep this body self-contained. */
export function verifyProviderPackFileLayout(
root: string | null,
policy: unknown,
fs: Pick<typeof import("node:fs"), "lstatSync" | "statSync" | "readdirSync">,
path: Pick<typeof import("node:path"), "join">,
): void {
if (policy === undefined) return; // Existing immutable packs retain their original contract.
if (policy !== "independent-regular-files-v1") throw new Error("runner_remote_provider_artifact_incompatible: provider pack file layout is unsupported");
if (root === null) return; // Bundled manifest identity has no controller-side asset tree.
// The caller may select an approved preinstalled-image root alias. Only this
// root follows that alias; interior directory symlinks remain untouched.
if (!fs.statSync(root).isDirectory()) throw new Error("runner_remote_provider_artifact_incompatible: provider pack file layout root is invalid");
const visit = (directory: string): void => {
for (const name of fs.readdirSync(directory)) {
const file = path.join(directory, name);
const stat = fs.lstatSync(file);
if (stat.isDirectory()) visit(file);
else if (stat.isFile()) {
if (stat.nlink !== 1) throw new Error("runner_remote_provider_artifact_incompatible: provider pack file layout requires independent regular files");
} else if (!stat.isSymbolicLink()) throw new Error("runner_remote_provider_artifact_incompatible: provider pack file layout entry is unsupported");
}
};
visit(root);
}