Files
PaperClipAI/tests/runner-e2e/installed-daytona-plugin.ts
DottaandPaperclip 30edeec300 test(runner): verify installed launch and published Daytona plugin
Invoke the public Playwright JavaScript entry directly for installed Pi tests so pnpm shim NODE_PATH injection cannot cross the closed controller boundary. Add a credential-free health/UI startup proof and a pinned published Daytona plugin fixture path without production runtime overrides.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-02 01:34:42 -05:00

73 lines
6.2 KiB
TypeScript

/** Public plugin fixture admission; the complete installed graph is audited separately. */
import { constants } from "node:fs";
import { lstat, open, realpath } from "node:fs/promises";
import { createHash } from "node:crypto";
import { findPackageJSON } from "node:module";
import { isAbsolute, join, resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { assertInstalledCliSelection, usesInstalledCli } from "./installed-cli.js";
import type { MatrixExecution } from "./types.js";
export const installedDaytonaPluginKeys = ["PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN", "PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN_AUTHORITY", "PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN_AUTHORITY_SHA256"] as const;
type PackagePin = { root: string; packageSha256: string; entry: string; entrySha256: string };
export interface InstalledDaytonaPluginAuthority {
schema: "paperclip.e2e.installed-daytona-plugin/v1";
graphRoot: string;
plugin: PackagePin & { manifestSha256: string; workerSha256: string };
sdk: PackagePin;
shared: PackagePin;
daytona: PackagePin;
}
const digest = (bytes: Buffer) => createHash("sha256").update(bytes).digest("hex");
async function canonical(path: string) {
if (typeof path !== "string" || !isAbsolute(path) || resolve(path) !== path || await realpath(path) !== path) throw new Error("Installed Daytona plugin path must be canonical and unlinked");
}
async function pinned(path: string, expected: string, maximum = 32 * 1024 * 1024) {
if (!/^[a-f0-9]{64}$/.test(expected)) throw new Error("Installed Daytona plugin requires a SHA-256 pin");
await canonical(path);
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
try {
const before = await handle.stat({ bigint: true });
if (!before.isFile() || before.size < 1n || before.size > BigInt(maximum) || before.nlink !== 1n) throw new Error("Installed Daytona plugin requires a bounded unlinked regular file");
const bytes = await handle.readFile(); const after = await handle.stat({ bigint: true }); const named = await lstat(path, { bigint: true });
if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs || named.dev !== before.dev || named.ino !== before.ino || bytes.length !== Number(before.size) || digest(bytes) !== expected) throw new Error("Installed Daytona plugin bytes differ from reviewed pins");
return bytes;
} finally { await handle.close(); }
}
function compiledEntry(manifest: any): string | undefined {
const exported = manifest.exports?.["."];
return typeof exported === "string" ? exported : (typeof exported?.import === "string" ? exported.import : exported?.import?.default) ?? manifest.main;
}
export async function verifyInstalledDaytonaPlugin(env: NodeJS.ProcessEnv, executions: readonly MatrixExecution[]) {
const selected = installedDaytonaPluginKeys.some(key => env[key] !== undefined);
const required = usesInstalledCli(env) && executions.some(e => e.environment.id === "daytona");
if (!selected && !required) return undefined;
assertInstalledCliSelection(env, executions);
if (!usesInstalledCli(env) || !installedDaytonaPluginKeys.every(key => Boolean(env[key])) || executions.some(e => e.environment.id !== "daytona")) throw new Error("Installed Daytona plugin requires complete pins and installed Pi Daytona selection");
const authorityPath = env.PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN_AUTHORITY!;
const authoritySha256 = env.PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN_AUTHORITY_SHA256!;
const a: InstalledDaytonaPluginAuthority = JSON.parse((await pinned(authorityPath, authoritySha256, 65536)).toString());
if (a.schema !== "paperclip.e2e.installed-daytona-plugin/v1" || a.plugin?.root !== env.PAPERCLIP_RUNNER_E2E_INSTALLED_DAYTONA_PLUGIN) throw new Error("Installed Daytona plugin authority differs");
await canonical(a.graphRoot);
async function packageAt(pin: PackagePin, name: string) {
await canonical(pin.root);
if (pin.root !== join(a.graphRoot, "node_modules", name)) throw new Error("Installed Daytona plugin package escapes its reviewed graph");
const manifest = JSON.parse((await pinned(join(pin.root, "package.json"), pin.packageSha256, 65536)).toString());
if (manifest.name !== name || typeof manifest.version !== "string" || !/^\d+\.\d+\.\d+(?:[-+][a-zA-Z0-9.-]+)?$/.test(manifest.version) || pin.entry !== (name === "@daytonaio/sdk" ? "./esm/index.js" : "./dist/index.js") || compiledEntry(manifest) !== pin.entry) throw new Error("Installed Daytona plugin requires published compiled package exports");
await pinned(join(pin.root, pin.entry), pin.entrySha256);
return manifest;
}
const plugin = await packageAt(a.plugin, "@paperclipai/plugin-daytona");
const sdk = await packageAt(a.sdk, "@paperclipai/plugin-sdk");
const shared = await packageAt(a.shared, "@paperclipai/shared");
const daytona = await packageAt(a.daytona, "@daytonaio/sdk");
if (plugin.paperclipPlugin?.manifest !== "./dist/manifest.js" || plugin.paperclipPlugin?.worker !== "./dist/worker.js" || plugin.dependencies?.["@paperclipai/plugin-sdk"] !== sdk.version || sdk.dependencies?.["@paperclipai/shared"] !== shared.version || plugin.dependencies?.["@daytonaio/sdk"] !== "0.203.0" || daytona.version !== "0.203.0") throw new Error("Installed Daytona plugin public dependency identity differs");
await pinned(join(a.plugin.root, "dist/manifest.js"), a.plugin.manifestSha256);
await pinned(join(a.plugin.root, "dist/worker.js"), a.plugin.workerSha256);
for (const [name, parent, pin] of [["@paperclipai/plugin-sdk", join(a.plugin.root, "dist/worker.js"), a.sdk], ["@paperclipai/shared", join(a.sdk.root, a.sdk.entry), a.shared], ["@daytonaio/sdk", join(a.plugin.root, "dist/worker.js"), a.daytona]] as const) {
const found = findPackageJSON(name, pathToFileURL(parent));
if (!found || await realpath(found) !== join(pin.root, "package.json")) throw new Error("Installed Daytona plugin resolves a foreign dependency");
}
return { schema: a.schema, authorityPath, authoritySha256, packageRoot: a.plugin.root, graphRoot: a.graphRoot, fullGraphVerified: false, completeGraphAuthorityRequired: true, sourceFallback: false };
}