#!/usr/bin/env node import { createHash } from "node:crypto"; import { readFile, readdir, writeFile } from "node:fs/promises"; import { resolve } from "node:path"; import process from "node:process"; const root = resolve(import.meta.dirname, ".."); const manifestPath = resolve(root, "config/v1-contract-freeze.json"); const files = ["backend/prisma/schema.prisma", "packages/contracts/index.js", "packages/contracts/index.d.ts", "docs/openapi/projectbrain-v1.json"]; const migrations = (await readdir(resolve(root, "backend/prisma/migrations"), { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(); const hashes = Object.fromEntries(await Promise.all(files.map(async (name) => [name, createHash("sha256").update(await readFile(resolve(root, name))).digest("hex")]))); const current = { version: "1.0.0", migrations, hashes }; if (process.argv.includes("--write")) { await writeFile(manifestPath, `${JSON.stringify(current, null, 2)}\n`); console.log(`Wrote v1 contract freeze manifest with ${migrations.length} migrations.`); } else { const frozen = JSON.parse(await readFile(manifestPath, "utf8")); if (JSON.stringify(frozen) !== JSON.stringify(current)) { console.error("The frozen v1 schema/API surface changed. Review compatibility and run pnpm freeze:v1 only for an approved release decision."); console.error("Current canonical v1 snapshot:"); console.error(JSON.stringify(current, null, 2)); process.exit(1); } console.log(`v1 contract freeze verified: ${files.length} canonical surfaces and ${migrations.length} migrations.`); }