import { randomBytes } from "node:crypto"; import { lstat, rename, unlink } from "node:fs/promises"; export type ProviderRawIdentity = Readonly<{ reportPath: string; reportDev: number; reportIno: number; }>; export async function cleanupOwnedProviderReport( identity: ProviderRawIdentity, ): Promise { try { const metadata = await lstat(identity.reportPath); if (!matchesReportIdentity(metadata, identity)) return false; const quarantine = `${identity.reportPath}.parent-loss-${process.pid}-${randomBytes(16).toString("hex")}`; await rename(identity.reportPath, quarantine); const quarantinedMetadata = await lstat(quarantine); if (!matchesReportIdentity(quarantinedMetadata, identity)) { throw new Error("provider raw output identity changed during parent-loss cleanup"); } await unlink(quarantine); return true; } catch (error) { if (hasErrorCode(error, "ENOENT")) return false; throw error; } } function matchesReportIdentity( metadata: Awaited>, identity: ProviderRawIdentity, ): boolean { return metadata.isFile() && !metadata.isSymbolicLink() && metadata.dev === identity.reportDev && metadata.ino === identity.reportIno; } function hasErrorCode(error: unknown, code: string): boolean { return Boolean(error && typeof error === "object" && "code" in error && error.code === code); }