49 lines
1.8 KiB
JavaScript
49 lines
1.8 KiB
JavaScript
import { readFile, readdir } from "node:fs/promises";
|
|
import path from "node:path";
|
|
|
|
const root = path.resolve("src");
|
|
const forbiddenSdk = /\b(?:new\s+Client|useClient|ClientProvider|useStream)\b/;
|
|
const forbiddenBrowserConfig =
|
|
/\b(?:deploymentUrl|langsmithApiKey|NEXT_PUBLIC_LANGSMITH_API_KEY)\b/;
|
|
const workspaceRoutes = [
|
|
"app/api/workspace/route.ts",
|
|
"app/api/workspace/file/route.ts",
|
|
"app/api/workspace/upload/route.ts",
|
|
"app/api/workspace/download/route.ts",
|
|
];
|
|
|
|
async function sourceFiles(directory) {
|
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
const files = [];
|
|
for (const entry of entries) {
|
|
const absolute = path.join(directory, entry.name);
|
|
if (entry.isDirectory()) files.push(...(await sourceFiles(absolute)));
|
|
else if (/\.(?:ts|tsx)$/.test(entry.name)) files.push(absolute);
|
|
}
|
|
return files;
|
|
}
|
|
|
|
const violations = [];
|
|
for (const file of await sourceFiles(root)) {
|
|
const relative = path.relative(root, file).replaceAll(path.sep, "/");
|
|
// Server-side BFF clients are intentionally the only LangGraph SDK clients.
|
|
if (relative.startsWith("lib/server/") || relative.startsWith("app/api/")) continue;
|
|
const source = await readFile(file, "utf8");
|
|
if (forbiddenSdk.test(source)) violations.push(`${relative} (LangGraph SDK)`);
|
|
if (forbiddenBrowserConfig.test(source)) {
|
|
violations.push(`${relative} (deployment credential or URL)`);
|
|
}
|
|
}
|
|
if (violations.length) {
|
|
throw new Error(`Browser BFF boundary violation: ${violations.join(", ")}`);
|
|
}
|
|
|
|
for (const route of workspaceRoutes) {
|
|
const source = await readFile(path.join(root, route), "utf8");
|
|
if (!source.includes("resolveConversationWorkspace")) {
|
|
throw new Error(`Workspace route is not scope-resolved: ${route}`);
|
|
}
|
|
}
|
|
|
|
console.log("Verified browser BFF boundary and conversation-scoped workspace routes.");
|