Files
neta/scripts/phase9-api-boundary.mjs
T

76 lines
2.1 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
const repoRoot = process.cwd();
const requiredRoutes = [
"app/.well-known/neta/route.ts",
"app/api/v1/meta/route.ts",
"app/api/v1/health/route.ts",
"app/api/v1/me/route.ts",
];
for (const route of requiredRoutes) {
assert.ok(fs.existsSync(path.join(repoRoot, route)), `Missing Phase 9 route: ${route}`);
}
const contracts = read("server/api/v1/contracts.ts");
for (const value of [
'NETA_PROTOCOL = "neta"',
"NETA_DISCOVERY_VERSION = 1",
'NETA_API_VERSION = "1"',
'"auth.device-pairing"',
'status: "planned"',
"minimumSupportedVersion",
]) {
assert.ok(contracts.includes(value), `Missing API contract marker: ${value}`);
}
const instanceService = read("server/instance/service.ts");
assert.doesNotMatch(
instanceService,
/next\/|Request\b|Response\b|cookies?\b|headers?\b/i,
"Instance service must stay independent from Next.js transport objects",
);
const discovery = read("app/.well-known/neta/route.ts");
assert.doesNotMatch(
discovery,
/getSession|requireSession|authorization/i,
"Discovery must remain public and session-independent",
);
for (const route of requiredRoutes.slice(1)) {
const content = read(route);
assert.match(content, /apiV1(?:Success|Error)/, `${route} must use the v1 envelope`);
}
for (const futureRoute of [
"app/api/v1/pairing-codes",
"app/api/v1/device-sessions",
]) {
assert.equal(
fs.existsSync(path.join(repoRoot, futureRoute)),
false,
`${futureRoute} must not ship before the pairing security design is implemented`,
);
}
const runtimeFiles = [
...requiredRoutes,
"server/api/v1/contracts.ts",
"server/api/v1/responses.ts",
"server/api/v1/runtime.ts",
"server/instance/service.ts",
"server/instance/runtime.ts",
"server/repositories/instance.ts",
];
for (const file of runtimeFiles) {
assert.doesNotMatch(read(file), /@supabase\/|supabase\.co/i, `Supabase reference in ${file}`);
}
console.log("Phase 9 API boundary passed: discovery, v1 contracts and pairing scope verified.");
function read(relativePath) {
return fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
}