Files
PaperClipAI/server/src/qualify-cloud-configuration.ts
T
DottaandPaperclip 8f822bfcf7 fix(cloud): persist configuration and load release-image packages (#18335)
Land the approved Cloud configuration and release-image package stack.

Includes the separately reviewed adapter settings (#18335), external adapters (#18333), bundled plugins (#18336), startup configuration (#18339), and migration/package checks (#18341).

Includes the final image-owned loader and linked-dependency inventory corrections.

Verified stack head: 462716170d.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 19:21:33 +00:00

48 lines
2.7 KiB
TypeScript

import path from "node:path";
import { pathToFileURL } from "node:url";
import { createDb } from "@paperclipai/db";
import { cloudConfigurationMigrationService } from "./services/cloud-configuration-migration.js";
import { qualifyCloudConfigurationForCurrentImage } from "./services/cloud-configuration-qualification.js";
export async function runCloudConfigurationQualification(args: string[], env: NodeJS.ProcessEnv = process.env): Promise<number> {
const allowed = new Set(["--migrate", "--expected-package-evidence", "--recheck-external-revision"]);
let migrate = false;
let expectedPackageEvidenceDigest: string | undefined;
let recheckRevision: number | undefined;
for (let index = 0; index < args.length; index += 1) {
const argument = args[index];
if (!allowed.has(argument)) throw new Error(`Unknown qualification argument: ${argument}`);
if (argument === "--migrate") migrate = true;
if (argument === "--expected-package-evidence") {
expectedPackageEvidenceDigest = args[++index];
if (!expectedPackageEvidenceDigest || !/^sha256:[a-f0-9]{64}$/.test(expectedPackageEvidenceDigest)) throw new Error("A SHA-256 package evidence digest is required");
}
if (argument === "--recheck-external-revision") {
const value = args[++index];
if (!value || !/^\d+$/.test(value) || !Number.isSafeInteger(Number(value))) throw new Error("A nonnegative receipt revision is required");
recheckRevision = Number(value);
}
}
const url = env.DATABASE_URL?.trim();
if (!url) throw new Error("DATABASE_URL is required for Cloud configuration qualification");
const db = createDb(url);
try {
const service = cloudConfigurationMigrationService(db, { runtimeEnv: env });
if (migrate) await service.migrate();
if (recheckRevision !== undefined) await service.recheckLegacyExternalRegistrations(recheckRevision);
const report = await qualifyCloudConfigurationForCurrentImage(db, { runtimeEnv: env, expectedPackageEvidenceDigest });
if (!report) throw new Error("Cloud configuration qualification requires a managed instance");
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
return report.configurationPackagesEligible && (!expectedPackageEvidenceDigest || report.samePackageOverlapEligible) ? 0 : 2;
} finally {
await db.$client.end({ timeout: 5 });
}
}
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
runCloudConfigurationQualification(process.argv.slice(2)).then((code) => { process.exitCode = code; }).catch((error) => {
process.stderr.write(`${error instanceof Error ? error.message : "Cloud configuration qualification failed"}\n`);
process.exitCode = 1;
});
}