mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-03 01:27:09 +01:00
feat(server): verify existing-volume ephemeral enrollment
Run owner migrations in a dedicated maintenance process, verify shared bytes, and export the original signing key only after complete eligibility. Validate with real PostgreSQL/S3 and the bundled executable. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
16787e4167
commit
dc450aa4bb
11 files changed
+544
-5
No files matched your search
@@ -71,10 +71,11 @@ function externalizeThirdParty(isBundled, runtimeDir) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function bundleRuntime({ entry, outdir, maintenanceEntry, isBundled = (specifier) => specifier.startsWith("@paperclipai/") }) {
|
||||
export async function bundleRuntime({ entry, outdir, maintenanceEntry, ephemeralMigrationEntry, isBundled = (specifier) => specifier.startsWith("@paperclipai/") }) {
|
||||
await rm(outdir, { recursive: true, force: true });
|
||||
const result = await build({
|
||||
entryPoints: { index: "paperclip-runtime-entry", server: entry, ...(maintenanceEntry ? { "agent-files": maintenanceEntry } : {}) },
|
||||
entryPoints: { index: "paperclip-runtime-entry", server: entry, ...(maintenanceEntry ? { "agent-files": maintenanceEntry } : {}),
|
||||
...(ephemeralMigrationEntry ? { "ephemeral-migration": ephemeralMigrationEntry } : {}) },
|
||||
outdir,
|
||||
outExtension: { ".js": ".mjs" },
|
||||
chunkNames: "chunk-[hash]",
|
||||
@@ -103,7 +104,8 @@ export async function bundleRuntime({ entry, outdir, maintenanceEntry, isBundled
|
||||
async function main() {
|
||||
const started = performance.now();
|
||||
const summary = await bundleRuntime({ entry: join(serverDir, "dist", "index.js"), outdir: join(serverDir, "dist-runtime"),
|
||||
maintenanceEntry: join(serverDir, "dist", "maintenance", "agent-files.js") });
|
||||
maintenanceEntry: join(serverDir, "dist", "maintenance", "agent-files.js"),
|
||||
ephemeralMigrationEntry: join(serverDir, "dist", "maintenance", "ephemeral-migration.js") });
|
||||
console.log(`[bundle-runtime] ${summary.inputs} inputs -> ${summary.chunks} chunks in ${Math.round(performance.now() - started)} ms: ${summary.outfile}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,15 @@ describe("bundleRuntime", () => {
|
||||
expect(JSON.parse(stdout)).toEqual({ asset: "asset beside its source", phase: "--phase=eligibility" });
|
||||
});
|
||||
|
||||
it("packages standalone enrollment without starting the app", async () => {
|
||||
const ephemeralMigrationEntry = path.join(root, "server", "dist", "migration.js");
|
||||
write(ephemeralMigrationEntry, 'import { values } from "@paperclipai/fixture"; console.log(JSON.stringify({ migrated: values.doubled }));');
|
||||
const outdir = path.join(root, "server", "dist-runtime");
|
||||
await bundleRuntime({ entry: path.join(root, "server", "dist", "index.js"), outdir, ephemeralMigrationEntry });
|
||||
const { stdout } = await execFileAsync(process.execPath, [path.join(outdir, "ephemeral-migration.mjs")], { timeout: 30_000 });
|
||||
expect(JSON.parse(stdout)).toEqual({ migrated: 42 });
|
||||
});
|
||||
|
||||
it("bundles workspace TypeScript and runs with plain node", async () => {
|
||||
const outdir = path.join(root, "server", "dist-runtime");
|
||||
const summary = await bundleRuntime({ entry: path.join(root, "server", "dist", "index.js"), outdir });
|
||||
|
||||
Reference in new issue
Block a user