Files
PaperClipAI/server/src/services/bundled-skill-release-validation.ts
T
Devin FoleyandPaperclip f0b597172b perf(skills): verify bundled releases with current inventory digests (#17652)
Use current scoped database inventory fingerprints and the current on-disk expectation before reusing bounded snapshot verification. Preserve full validation, seeding and access checks when content, expectation or row existence changes.

Verified177 skill and authorization tests, workspace typechecking, server build, all green CI and exact-head Apex5/5. Prior staging release measured and saved Legacy data fingerprints preserved.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 13:37:11 -07:00

46 lines
2.0 KiB
TypeScript

import { companySkillVersions, type Db } from "@paperclipai/db";
import { and, eq, getTableColumns, sql } from "drizzle-orm";
type Version = typeof companySkillVersions.$inferSelect;
type Verification = { inventorySha256: string; expectedInventoryHash: string };
const verifiedInventories = new WeakMap<Db, Map<string, Verification>>();
const inventorySha256 = sql<string>`encode(sha256(convert_to(${companySkillVersions.fileInventory}::text, 'UTF8')), 'hex')`;
export async function verifyExistingBundledSkillRelease(input: {
db: Db;
companyId: string;
skillId: string;
releaseId: string;
expectedInventoryHash: string;
validateInventory: (version: Version) => void | Promise<void>;
}): Promise<boolean> {
const scope = and(eq(companySkillVersions.companyId, input.companyId),
eq(companySkillVersions.companySkillId, input.skillId), eq(companySkillVersions.releaseId, input.releaseId));
const [current] = await input.db.select({ id: companySkillVersions.id, inventorySha256 })
.from(companySkillVersions).where(scope).limit(1);
if (!current) return false;
let verified = verifiedInventories.get(input.db);
if (!verified) {
verified = new Map();
verifiedInventories.set(input.db, verified);
}
const previous = verified.get(current.id);
if (previous?.inventorySha256 === current.inventorySha256
&& previous.expectedInventoryHash === input.expectedInventoryHash) {
verified.delete(current.id);
verified.set(current.id, previous);
return true;
}
const [version] = await input.db.select({ ...getTableColumns(companySkillVersions), inventorySha256 })
.from(companySkillVersions).where(scope).limit(1);
if (!version) return false;
await input.validateInventory(version);
verified.delete(version.id);
verified.set(version.id, { inventorySha256: version.inventorySha256, expectedInventoryHash: input.expectedInventoryHash });
while (verified.size > 64) {
const oldest = verified.keys().next().value;
if (oldest !== undefined) verified.delete(oldest);
}
return true;
}