refactor(workspaces): finalize runtime package boundaries

Keep the daemon dependent only on the public runtime contract and helper, while optional runtime implementations remain external command registrations. Workspace setup continues asynchronously through the bound runtime without coupling production packages to an implementation.
This commit is contained in:
Mohamed Boudra
2026-08-14 12:48:35 +02:00
parent 36d8464068
commit 7c32fcda98
85 changed files with 2293 additions and 4664 deletions
+337 -94
View File
@@ -7,7 +7,13 @@ import { fileURLToPath } from "node:url";
import ts from "typescript";
const SERVER_ROOT = "packages/server/src/server";
const FIXTURE_ROOT = "packages/fixture-workspace-runtime";
const CORE_SOURCE_ROOTS = [
"packages/server/src",
"packages/cli/src",
"packages/desktop/src",
"packages/app/src",
];
const IN_REPO_RUNTIME_ROOTS = ["runtimes/fixture"];
const migratedOwners = [
"/session/files/",
"/session/git-mutation/",
@@ -17,11 +23,22 @@ const migratedOwners = [
"/session/workspace-scripts/",
];
const hostModules = new Set(["child_process", "fs", "fs/promises", "module", "which"]);
const auditedNonliteralServerLoads = new Set([
"packages/server/src/server/workspace-runtime/command/internal/command-runtime.ts|resolveRuntimeCommand|moduleRequire|resolve",
"packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts|resolveSherpaLoaderEnv|require|resolve",
"packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts|loadWithRequire|requireFn|load",
]);
export async function findWorkspaceBoundaryViolations(repoRoot) {
const files = [
...(await collectSources(path.join(repoRoot, SERVER_ROOT))),
...(await collectSources(path.join(repoRoot, FIXTURE_ROOT))),
...(
await Promise.all(CORE_SOURCE_ROOTS.map((root) => collectSources(path.join(repoRoot, root))))
).flat(),
...(
await Promise.all(
IN_REPO_RUNTIME_ROOTS.map((root) => collectSources(path.join(repoRoot, root))),
)
).flat(),
];
const modules = await Promise.all(
files.map(async (filename) => {
@@ -35,33 +52,15 @@ export async function findWorkspaceBoundaryViolations(repoRoot) {
.map(({ filename }) => toRepoPath(repoRoot, filename)),
);
const violations = [];
for (const { filename, sourceFile } of modules) {
const importer = toRepoPath(repoRoot, filename);
const external = importer.startsWith(`${FIXTURE_ROOT}/`);
const governed =
external ||
(!isTestFile(importer) && (ownsMigratedSurface(importer) || publicOwners.has(importer)));
for (const specifier of staticSpecifiers(sourceFile)) {
if (!isTestFile(importer) && isForbiddenInternal(importer, specifier)) {
violations.push(violation(importer, specifier, "module-entrypoint"));
}
}
for (const load of moduleLoads(sourceFile)) {
if (load.specifier === null) {
if (governed) violations.push(violation(importer, "<computed>", "nonliteral-module-load"));
continue;
}
const specifier = load.specifier;
if (isForbiddenInternal(importer, specifier)) {
violations.push(violation(importer, specifier, "module-entrypoint"));
}
if (governed && !external && isHostCapability(specifier)) {
violations.push(violation(importer, specifier, "workspace-host-access"));
}
if (external && isExternalEscape(importer, specifier)) {
violations.push(violation(importer, specifier, "external-runtime-contract"));
}
}
for (const runtimeRoot of IN_REPO_RUNTIME_ROOTS) {
const ownedModules = modules.filter(({ filename }) =>
toRepoPath(repoRoot, filename).startsWith(`${runtimeRoot}/`),
);
const duplicateHelper = duplicateWorkspaceHelperViolation(repoRoot, runtimeRoot, ownedModules);
if (duplicateHelper) violations.push(duplicateHelper);
}
for (const module of modules) {
violations.push(...moduleViolations(repoRoot, module, publicOwners));
}
return violations.sort((left, right) =>
`${left.file}:${left.import}:${left.rule}`.localeCompare(
@@ -70,6 +69,68 @@ export async function findWorkspaceBoundaryViolations(repoRoot) {
);
}
function moduleViolations(repoRoot, { filename, sourceFile }, publicOwners) {
const importer = toRepoPath(repoRoot, filename);
const external = IN_REPO_RUNTIME_ROOTS.some((root) => importer.startsWith(`${root}/`));
const testFile = isTestFile(importer);
const serverProduction = importer.startsWith(`${SERVER_ROOT}/`) && !testFile;
const governed =
external || (!testFile && (ownsMigratedSurface(importer) || publicOwners.has(importer)));
const violations = [];
for (const specifier of staticSpecifiers(sourceFile)) {
if (isExternalRuntimeAccess(importer, specifier)) {
violations.push(violation(importer, specifier, "server-runtime-access"));
}
if (!testFile && isForbiddenInternal(importer, specifier)) {
violations.push(violation(importer, specifier, "module-entrypoint"));
}
if (external && !testFile && isExternalEscape(importer, specifier)) {
violations.push(violation(importer, specifier, "external-runtime-contract"));
}
}
for (const load of moduleLoads(sourceFile)) {
violations.push(...loadViolations({ importer, external, governed, serverProduction, load }));
}
return violations;
}
function loadViolations({ importer, external, governed, serverProduction, load }) {
if (load.specifier === null) {
const audited = isAuditedNonliteralServerLoad(importer, load);
return external || (serverProduction && !audited)
? [violation(importer, "<computed>", "nonliteral-module-load")]
: [];
}
const violations = [];
if (isExternalRuntimeAccess(importer, load.specifier)) {
violations.push(violation(importer, load.specifier, "server-runtime-access"));
}
if (isForbiddenInternal(importer, load.specifier)) {
violations.push(violation(importer, load.specifier, "module-entrypoint"));
}
if (governed && !external && isHostCapability(load.specifier)) {
violations.push(violation(importer, load.specifier, "workspace-host-access"));
}
if (external && isExternalEscape(importer, load.specifier)) {
violations.push(violation(importer, load.specifier, "external-runtime-contract"));
}
return violations;
}
function implementsWorkspaceHelper(source) {
return ["fs-stat", "fs-list", "fs-read", "fs-write"].every((command) => source.includes(command));
}
function duplicateWorkspaceHelperViolation(repoRoot, runtimeRoot, modules) {
const combinedSource = modules.map(({ sourceFile }) => sourceFile.text).join("\n");
if (!implementsWorkspaceHelper(combinedSource)) return null;
const singleFileOwner = modules.find(({ sourceFile }) =>
implementsWorkspaceHelper(sourceFile.text),
);
const owner = singleFileOwner ? toRepoPath(repoRoot, singleFileOwner.filename) : runtimeRoot;
return violation(owner, "workspace-helper protocol", "duplicate-workspace-helper");
}
function parseSource(filename, source) {
return ts.createSourceFile(
filename,
@@ -96,61 +157,43 @@ function staticSpecifiers(sourceFile) {
function moduleLoads(sourceFile) {
const loads = [];
const constants = constantBindings(sourceFile);
const loaderAliases = moduleLoaderAliases(sourceFile);
visit(sourceFile);
return loads;
function visit(node) {
if (
ts.isCallExpression(node) &&
(node.expression.kind === ts.SyntaxKind.ImportKeyword ||
(ts.isIdentifier(node.expression) && loaderAliases.has(node.expression.text)))
) {
if (ts.isCallExpression(node)) {
const load = moduleLoad(node.expression, loaderAliases);
if (!load) {
ts.forEachChild(node, visit);
return;
}
const argument = node.arguments.length === 1 ? node.arguments[0] : undefined;
loads.push({ specifier: argument ? constantString(argument, constants) : null });
loads.push({
...load,
owner: enclosingFunctionName(node),
specifier: argument ? literalModuleSpecifier(argument) : null,
});
}
ts.forEachChild(node, visit);
}
}
function constantBindings(sourceFile) {
const constants = new Map();
let changed = true;
while (changed) {
changed = false;
for (const statement of sourceFile.statements) {
if (!ts.isVariableStatement(statement)) continue;
if (!(statement.declarationList.flags & ts.NodeFlags.Const)) continue;
for (const declaration of statement.declarationList.declarations) {
if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;
const value = constantString(declaration.initializer, constants);
if (value === null || constants.get(declaration.name.text) === value) continue;
constants.set(declaration.name.text, value);
changed = true;
}
}
}
return constants;
}
function moduleLoaderAliases(sourceFile) {
const aliases = new Set(["require"]);
const declarations = variableDeclarations(sourceFile);
const moduleObjects = moduleObjectAliases(sourceFile, declarations);
const factories = createRequireAliases(sourceFile, declarations, moduleObjects);
collectNodeRequireParameters(sourceFile, aliases);
let changed = true;
while (changed) {
changed = false;
for (const statement of sourceFile.statements) {
if (!ts.isVariableStatement(statement)) continue;
for (const declaration of statement.declarationList.declarations) {
if (
!ts.isIdentifier(declaration.name) ||
!declaration.initializer ||
!ts.isIdentifier(declaration.initializer) ||
!aliases.has(declaration.initializer.text) ||
aliases.has(declaration.name.text)
) {
continue;
}
for (const declaration of declarations) {
if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;
const aliasesLoader =
ts.isIdentifier(declaration.initializer) && aliases.has(declaration.initializer.text);
const createsLoader = isCreateRequireCall(declaration.initializer, factories, moduleObjects);
if ((aliasesLoader || createsLoader) && !aliases.has(declaration.name.text)) {
aliases.add(declaration.name.text);
changed = true;
}
@@ -159,34 +202,219 @@ function moduleLoaderAliases(sourceFile) {
return aliases;
}
function constantString(expression, constants) {
function isCreateRequireCall(expression, factories, moduleObjects) {
if (!ts.isCallExpression(expression)) return false;
return (
(ts.isIdentifier(expression.expression) && factories.has(expression.expression.text)) ||
isCreateRequireProperty(expression.expression, moduleObjects)
);
}
function variableDeclarations(sourceFile) {
const declarations = [];
visit(sourceFile);
return declarations;
function visit(node) {
if (ts.isVariableDeclaration(node)) declarations.push(node);
ts.forEachChild(node, visit);
}
}
function literalModuleSpecifier(expression) {
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {
return expression.text;
}
if (ts.isIdentifier(expression)) return constants.get(expression.text) ?? null;
if (ts.isParenthesizedExpression(expression)) {
return constantString(expression.expression, constants);
return null;
}
function moduleLoad(expression, loaderAliases) {
if (expression.kind === ts.SyntaxKind.ImportKeyword) {
return { loader: "import", operation: "import" };
}
if (ts.isIdentifier(expression) && loaderAliases.has(expression.text)) {
return { loader: expression.text, operation: "load" };
}
if (
ts.isBinaryExpression(expression) &&
expression.operatorToken.kind === ts.SyntaxKind.PlusToken
ts.isPropertyAccessExpression(expression) &&
ts.isIdentifier(expression.expression) &&
loaderAliases.has(expression.expression.text) &&
expression.name.text === "resolve"
) {
const left = constantString(expression.left, constants);
const right = constantString(expression.right, constants);
return left === null || right === null ? null : left + right;
}
if (ts.isTemplateExpression(expression)) {
let value = expression.head.text;
for (const span of expression.templateSpans) {
const substitution = constantString(span.expression, constants);
if (substitution === null) return null;
value += substitution + span.literal.text;
}
return value;
return { loader: expression.expression.text, operation: "resolve" };
}
return null;
}
function createRequireAliases(sourceFile, declarations, moduleObjects) {
const aliases = importedCreateRequireAliases(sourceFile);
let changed = true;
while (changed) {
changed = addCreateRequireAliases(aliases, moduleObjects, declarations);
}
return aliases;
}
function importedCreateRequireAliases(sourceFile) {
const aliases = new Set();
for (const statement of sourceFile.statements) {
if (!isNamedModuleImport(statement)) continue;
for (const element of statement.importClause.namedBindings.elements) {
if ((element.propertyName ?? element.name).text === "createRequire") {
aliases.add(element.name.text);
}
}
}
return aliases;
}
function addCreateRequireAliases(aliases, moduleObjects, declarations) {
let changed = false;
for (const declaration of declarations) {
for (const alias of createRequireBindingNames(declaration, aliases, moduleObjects)) {
if (aliases.has(alias)) continue;
aliases.add(alias);
changed = true;
}
}
return changed;
}
function createRequireBindingNames(declaration, aliases, moduleObjects) {
if (!declaration.initializer) return [];
if (ts.isIdentifier(declaration.name)) {
const initializer = declaration.initializer;
const factory =
(ts.isIdentifier(initializer) && aliases.has(initializer.text)) ||
isCreateRequireProperty(initializer, moduleObjects);
return factory ? [declaration.name.text] : [];
}
if (!ts.isObjectBindingPattern(declaration.name)) return [];
if (!isModuleObjectExpression(declaration.initializer, moduleObjects)) return [];
return declaration.name.elements
.filter(
(element) =>
ts.isIdentifier(element.name) && bindingPropertyName(element) === "createRequire",
)
.map((element) => element.name.text);
}
function isNamedModuleImport(statement) {
return (
ts.isImportDeclaration(statement) &&
statement.importClause?.namedBindings &&
ts.isNamedImports(statement.importClause.namedBindings) &&
ts.isStringLiteral(statement.moduleSpecifier) &&
["module", "node:module"].includes(statement.moduleSpecifier.text)
);
}
function moduleObjectAliases(sourceFile, declarations) {
const aliases = new Set();
for (const statement of sourceFile.statements) {
if (
ts.isImportDeclaration(statement) &&
statement.importClause?.namedBindings &&
ts.isNamespaceImport(statement.importClause.namedBindings) &&
ts.isStringLiteral(statement.moduleSpecifier) &&
["module", "node:module"].includes(statement.moduleSpecifier.text)
) {
aliases.add(statement.importClause.namedBindings.name.text);
}
}
let changed = true;
while (changed) {
changed = false;
for (const declaration of declarations) {
if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue;
if (
!isModuleObjectExpression(declaration.initializer, aliases) ||
aliases.has(declaration.name.text)
) {
continue;
}
aliases.add(declaration.name.text);
changed = true;
}
}
return aliases;
}
function isCreateRequireProperty(expression, moduleObjects) {
return (
staticPropertyName(expression) === "createRequire" &&
isModuleObjectExpression(expression.expression, moduleObjects)
);
}
function isModuleObjectExpression(expression, moduleObjects) {
return (
(ts.isIdentifier(expression) && moduleObjects.has(expression.text)) ||
isModuleRequireCall(expression)
);
}
function staticPropertyName(expression) {
if (ts.isPropertyAccessExpression(expression)) return expression.name.text;
if (ts.isElementAccessExpression(expression) && expression.argumentExpression) {
return literalModuleSpecifier(expression.argumentExpression);
}
return null;
}
function bindingPropertyName(element) {
const property = element.propertyName ?? element.name;
if (ts.isIdentifier(property) || ts.isStringLiteral(property)) return property.text;
if (ts.isComputedPropertyName(property)) return literalModuleSpecifier(property.expression);
return null;
}
function isModuleRequireCall(expression) {
return (
ts.isCallExpression(expression) &&
ts.isIdentifier(expression.expression) &&
expression.expression.text === "require" &&
expression.arguments.length === 1 &&
ts.isStringLiteral(expression.arguments[0]) &&
["module", "node:module"].includes(expression.arguments[0].text)
);
}
function collectNodeRequireParameters(sourceFile, aliases) {
visit(sourceFile);
function visit(node) {
if (
ts.isParameter(node) &&
ts.isIdentifier(node.name) &&
node.type?.getText() === "NodeRequire"
) {
aliases.add(node.name.text);
}
ts.forEachChild(node, visit);
}
}
function enclosingFunctionName(node) {
for (let current = node.parent; current; current = current.parent) {
if (ts.isFunctionDeclaration(current) && current.name) return current.name.text;
if (ts.isMethodDeclaration(current) && ts.isIdentifier(current.name)) return current.name.text;
if (
(ts.isArrowFunction(current) || ts.isFunctionExpression(current)) &&
ts.isVariableDeclaration(current.parent) &&
ts.isIdentifier(current.parent.name)
) {
return current.parent.name.text;
}
}
return "<module>";
}
function isAuditedNonliteralServerLoad(importer, load) {
return auditedNonliteralServerLoads.has(
[importer, load.owner, load.loader, load.operation].join("|"),
);
}
function isPublicEntryPoint(specifier) {
return /workspace-(?:runtime|helper)\/index\.(?:js|ts)$/.test(specifier);
}
@@ -231,11 +459,7 @@ function isForbiddenInternal(importer, specifier) {
);
}
if (target.includes("/workspace-helper/internal/")) {
return !(
importer.endsWith("/workspace-helper/index.ts") ||
importer.includes("/workspace-helper/internal/") ||
importer.endsWith("/workspace-runtime/internal/service.ts")
);
return true;
}
return false;
}
@@ -246,11 +470,16 @@ function isExternalEscape(importer, specifier) {
if (specifier.startsWith("node:") || hostModules.has(specifier) || specifier === "node-pty") {
return false;
}
if (specifier === "@getpaseo/workspace-runtime-contract") return false;
if (
specifier === "@getpaseo/workspace-runtime-contract" ||
specifier === "@getpaseo/workspace-helper"
)
return false;
if (path.posix.isAbsolute(specifier) || specifier.startsWith("file:")) return true;
if (specifier.startsWith(".")) {
const target = path.posix.normalize(path.posix.join(path.posix.dirname(importer), specifier));
return !target.startsWith(`${FIXTURE_ROOT}/`);
const owner = IN_REPO_RUNTIME_ROOTS.find((root) => importer.startsWith(`${root}/`));
return !owner || !target.startsWith(`${owner}/`);
}
return (
specifier === "@getpaseo/server" ||
@@ -260,6 +489,20 @@ function isExternalEscape(importer, specifier) {
);
}
function isExternalRuntimeAccess(importer, specifier) {
if (!CORE_SOURCE_ROOTS.some((root) => importer.startsWith(`${root}/`))) return false;
if (/^@getpaseo\/(?:docker|fixture|srt)-workspace-runtime(?:\/|$)/u.test(specifier)) {
return true;
}
if (/paseo-workspace-runtime-(?:docker|srt)|runtimes\/(?:docker|srt)(?:\/|$)/u.test(specifier)) {
return true;
}
const target = resolveSpecifier(importer, specifier);
return IN_REPO_RUNTIME_ROOTS.some(
(runtimeRoot) => target === runtimeRoot || target.startsWith(`${runtimeRoot}/`),
);
}
function resolveSpecifier(importer, specifier) {
if (specifier.startsWith(".")) {
return path.posix.normalize(path.posix.join(path.posix.dirname(importer), specifier));
+5 -1
View File
@@ -120,6 +120,9 @@ test("focused contracts stay inside existing required checks", () => {
assert.match(server, /test:hub-cli-contract/);
assert.match(server, /npm test --workspace=@getpaseo\/workspace-runtime-contract/);
assert.match(server, /npm test --workspace=@getpaseo\/workspace-helper/);
assert.match(server, /node --test scripts\/workspace-runtime-standalone\.test\.mjs/);
assert.match(server, /node --test scripts\/server-clean-build\.test\.mjs/);
assert.match(server, /npm run test --workspace=@getpaseo\/server/);
assert.ok(!jobs.has("hub-cli-contract"));
@@ -162,7 +165,8 @@ test("PR routing declares stable behavior ownership", () => {
hub: ["packages/cli/src/commands/hub/**", "packages/server/src/server/hub/**"],
server: [
"packages/server/**",
"packages/fixture-workspace-runtime/**",
"runtimes/fixture/**",
"packages/workspace-helper/**",
"packages/workspace-runtime-contract/**",
"packages/app/e2e/support/fixtures/recording.*",
],
+130
View File
@@ -0,0 +1,130 @@
import { execFile } from "node:child_process";
import { access, cp, mkdir, mkdtemp, readFile, readdir, rm, symlink } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import assert from "node:assert/strict";
import { promisify } from "node:util";
const run = promisify(execFile);
const repoRoot = path.resolve(import.meta.dirname, "..");
const packageDirectories = [
"packages/highlight",
"packages/relay",
"packages/protocol",
"packages/client",
"packages/workspace-runtime-contract",
"packages/workspace-helper",
"packages/server",
"packages/cli",
];
test("build:server:clean constructs public prerequisites without runtime implementations", async (t) => {
const isolatedRoot = await mkdtemp(path.join(os.tmpdir(), "paseo-server-clean-build-"));
t.after(() => rm(isolatedRoot, { recursive: true, force: true }));
await copyBuildCheckout(isolatedRoot);
await createNodeModulesOverlay(isolatedRoot);
await createPackageNodeModulesOverlays(isolatedRoot);
for (const relativePath of [
"packages/workspace-runtime-contract/dist",
"packages/workspace-helper/dist",
"packages/server/dist",
]) {
await assert.rejects(access(path.join(isolatedRoot, relativePath)), relativePath);
}
await assert.rejects(access(path.join(isolatedRoot, "runtimes")));
try {
await run("npm", ["run", "build:server:clean"], {
cwd: isolatedRoot,
timeout: 120_000,
});
} catch (error) {
assert.fail(`${error.stdout ?? ""}\n${error.stderr ?? ""}`);
}
for (const relativePath of [
"packages/workspace-runtime-contract/dist/index.js",
"packages/workspace-helper/dist/index.js",
"packages/server/dist/server/server/exports.js",
"packages/cli/dist/index.js",
]) {
await access(path.join(isolatedRoot, relativePath));
}
await assert.rejects(access(path.join(isolatedRoot, "runtimes")));
});
async function copyBuildCheckout(isolatedRoot) {
await Promise.all([
...["package.json", "package-lock.json", "tsconfig.base.json", "tsconfig.json"].map((file) =>
cp(path.join(repoRoot, file), path.join(isolatedRoot, file)),
),
cp(path.join(repoRoot, "scripts"), path.join(isolatedRoot, "scripts"), {
recursive: true,
filter: excludesBuildOutput,
}),
...packageDirectories.map(async (relativeDirectory) => {
const target = path.join(isolatedRoot, relativeDirectory);
await mkdir(path.dirname(target), { recursive: true });
await cp(path.join(repoRoot, relativeDirectory), target, {
recursive: true,
filter: excludesBuildOutput,
});
}),
]);
}
function excludesBuildOutput(source) {
return (
!source.endsWith(`${path.sep}dist`) &&
!source.endsWith(`${path.sep}node_modules`) &&
!source.endsWith(`${path.sep}test-results`)
);
}
async function createNodeModulesOverlay(isolatedRoot) {
const sourceModules = path.join(repoRoot, "node_modules");
const targetModules = path.join(isolatedRoot, "node_modules");
await mkdir(targetModules);
await overlayModules(sourceModules, targetModules);
const internalScope = path.join(targetModules, "@getpaseo");
await mkdir(internalScope);
for (const relativeDirectory of packageDirectories) {
const manifest = JSON.parse(
await readFile(path.join(isolatedRoot, relativeDirectory, "package.json"), "utf8"),
);
await symlink(
path.join(isolatedRoot, relativeDirectory),
path.join(internalScope, manifest.name.slice("@getpaseo/".length)),
"dir",
);
}
}
async function createPackageNodeModulesOverlays(isolatedRoot) {
for (const relativeDirectory of packageDirectories) {
const sourceModules = path.join(repoRoot, relativeDirectory, "node_modules");
try {
await access(sourceModules);
} catch {
continue;
}
const targetModules = path.join(isolatedRoot, relativeDirectory, "node_modules");
await mkdir(targetModules);
await overlayModules(sourceModules, targetModules);
}
}
async function overlayModules(sourceModules, targetModules) {
for (const entry of await readdir(sourceModules, { withFileTypes: true })) {
if (entry.name === "@getpaseo") continue;
await symlink(
path.join(sourceModules, entry.name),
path.join(targetModules, entry.name),
entry.isDirectory() ? "dir" : "file",
);
}
}
+342 -22
View File
@@ -1,5 +1,14 @@
import { execFile } from "node:child_process";
import { copyFile, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import {
access,
copyFile,
mkdir,
mkdtemp,
readFile,
readdir,
rm,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
@@ -13,6 +22,77 @@ const run = promisify(execFile);
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const oxlint = path.join(repoRoot, "node_modules/.bin/oxlint");
test("Paseo owns only the public runtime packages and generic fixture", async () => {
const rootPackage = JSON.parse(await readFile(path.join(repoRoot, "package.json"), "utf8"));
assert.ok(rootPackage.workspaces.includes("packages/workspace-helper"));
assert.ok(rootPackage.workspaces.includes("packages/workspace-runtime-contract"));
assert.ok(rootPackage.workspaces.includes("runtimes/fixture"));
assert.ok(!rootPackage.workspaces.includes("runtimes/*"));
for (const script of [
"build:docker-workspace-runtime",
"build:docker-workspace-runtime:clean",
"build:srt-workspace-runtime",
]) {
assert.equal(rootPackage.scripts?.[script], undefined);
}
await assert.rejects(access(path.join(repoRoot, "packages/server/src/server/workspace-helper")));
for (const absent of [
"packages/docker-workspace-runtime",
"packages/fixture-workspace-runtime",
"packages/srt-workspace-runtime",
"runtimes/docker",
"runtimes/srt",
]) {
await assert.rejects(access(path.join(repoRoot, absent)), absent);
}
const helper = JSON.parse(
await readFile(path.join(repoRoot, "packages/workspace-helper/package.json"), "utf8"),
);
assert.equal(helper.name, "@getpaseo/workspace-helper");
assert.equal(helper.private, undefined);
assert.equal(helper.bin?.["paseo-workspace-helper"], "./dist/executable.mjs");
const server = JSON.parse(
await readFile(path.join(repoRoot, "packages/server/package.json"), "utf8"),
);
assert.ok(server.dependencies?.["@getpaseo/workspace-helper"]);
assert.ok(server.dependencies?.["@getpaseo/workspace-runtime-contract"]);
for (const runtime of ["docker", "fixture", "srt"]) {
assert.equal(server.dependencies?.[`@getpaseo/${runtime}-workspace-runtime`], undefined);
}
const fixtureDirectory = path.join(repoRoot, "runtimes/fixture");
const fixture = JSON.parse(await readFile(path.join(fixtureDirectory, "package.json"), "utf8"));
for (const dependency of ["@getpaseo/workspace-runtime-contract", "@getpaseo/workspace-helper"]) {
assert.match(fixture.dependencies?.[dependency] ?? "", /^\d+\.\d+\.\d+(?:[-+].*)?$/u);
}
const fixtureSources = await collectRuntimeSources(fixtureDirectory);
assert.doesNotMatch(
fixtureSources,
/packages\/(?:server|app|cli|desktop|test-utils)|@getpaseo\/server|docker|sandbox-runtime|\bsrt\b/iu,
);
const lockfile = await readFile(path.join(repoRoot, "package-lock.json"), "utf8");
assert.doesNotMatch(
lockfile,
/node_modules\/@getpaseo\/(?:docker|srt)-workspace-runtime|"runtimes\/(?:docker|srt)"/u,
);
for (const relativePath of [
".github/ci-paths.yml",
".github/workflows/ci.yml",
".github/workflows/docker.yml",
"docs/architecture.md",
"docs/docker.md",
"public-docs/configuration.md",
]) {
const contents = await readFile(path.join(repoRoot, relativePath), "utf8");
assert.doesNotMatch(contents, /runtimes\/(?:docker|srt)/u, relativePath);
}
});
test("Oxlint rejects static host imports, re-exports, aliases, and internal package paths", async (t) => {
const root = await fixtureRoot(t);
await copyFile(path.join(repoRoot, ".oxlintrc.json"), path.join(root, ".oxlintrc.json"));
@@ -29,25 +109,25 @@ test("Oxlint rejects static host imports, re-exports, aliases, and internal pack
'export * from "@getpaseo/server/workspace-runtime/internal/service.js";\n' +
'export * from "@getpaseo/server/workspace-runtime/command/internal/command-runtime.js";\n' +
'export * from "@getpaseo/server/workspace-runtime/git-observation/internal/integration.js";\n' +
'export { default as helper } from "../../workspace-helper/internal/client.js";\n' +
'export { default as helper } from "@getpaseo/workspace-helper/internal/client.js";\n' +
"void spawn; void readFile;\n",
);
await source(
root,
"packages/fixture-workspace-runtime/src/forbidden.mjs",
"runtimes/fixture/src/forbidden.mjs",
'import "@getpaseo/server/workspace-runtime/command/internal/command-runtime.js";\n' +
'import { createRequire as externalRequire } from "module";\n' +
"const fixtureLoader = externalRequire(import.meta.url);\n" +
'fixtureLoader("node:fs");\n' +
'export * from "../../../packages/server/src/server/workspace-helper/internal/client.js";\n',
'export * from "@getpaseo/workspace-helper/internal/client.js";\n',
);
const error = await captureFailure(run(oxlint, ["packages"], { cwd: root }));
const error = await captureFailure(run(oxlint, ["packages", "runtimes"], { cwd: root }));
const output = `${error.stdout ?? ""}${error.stderr ?? ""}`;
assert.match(output, /child_process/);
assert.match(output, /node:fs\/promises/);
assert.match(output, /node:module/);
assert.match(output, /'module'/);
assert.match(output, /module/);
assert.match(output, /workspace-runtime\/internal/);
assert.match(output, /workspace-runtime\/command\/internal/);
assert.match(output, /git-observation\/internal/);
@@ -74,7 +154,7 @@ test("the AST guard rejects computed loading and dynamic host/internal bypasses"
);
await source(
root,
"packages/fixture-workspace-runtime/src/forbidden.mjs",
"runtimes/fixture/src/forbidden.mjs",
'require("../../../packages/server/src/server/workspace-runtime/internal/service.js");\n' +
'import("@getpaseo/" + packageName);\n',
);
@@ -88,6 +168,7 @@ test("the AST guard rejects computed loading and dynamic host/internal bypasses"
"module-entrypoint",
"nonliteral-module-load",
"nonliteral-module-load",
"nonliteral-module-load",
"workspace-host-access",
"workspace-host-access",
"workspace-host-access",
@@ -96,6 +177,239 @@ test("the AST guard rejects computed loading and dynamic host/internal bypasses"
);
});
test("the AST guard rejects server access to runtime packages and source roots", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"packages/server/src/server/runtime-bypass.ts",
'import "@getpaseo/docker-workspace-runtime";\n' +
'export * from "@getpaseo/srt-workspace-runtime";\n' +
'import "../../../../../../paseo-workspace-runtime-docker/src/index.ts";\n' +
'export * from "../../../../../../paseo-workspace-runtime-srt/src/index.mjs";\n' +
'const packageName = "@getpaseo/" + "fixture-workspace-runtime";\n' +
'const sourceRoot = "../../../../runtimes/" + "docker/src/index.ts";\n' +
"const load = require;\n" +
"void load(packageName);\n" +
"void import(sourceRoot);\n",
);
const violations = await findWorkspaceBoundaryViolations(root);
assert.equal(violations.length, 6);
assert.deepEqual(violations.map(({ rule }) => rule).sort(), [
"nonliteral-module-load",
"nonliteral-module-load",
"server-runtime-access",
"server-runtime-access",
"server-runtime-access",
"server-runtime-access",
]);
assert.deepEqual(
new Set(violations.map((violation) => violation.import)),
new Set([
"@getpaseo/docker-workspace-runtime",
"@getpaseo/srt-workspace-runtime",
"../../../../../../paseo-workspace-runtime-docker/src/index.ts",
"../../../../../../paseo-workspace-runtime-srt/src/index.mjs",
"<computed>",
]),
);
});
test("the AST guard rejects every nonliteral production server load", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"packages/server/src/server/nonliteral-runtime-load.ts",
'const target = ["@getpaseo/docker", "-workspace-runtime"].join("");\n' +
"void import(target);\n",
);
assert.deepEqual(await findWorkspaceBoundaryViolations(root), [
{
file: "packages/server/src/server/nonliteral-runtime-load.ts",
import: "<computed>",
rule: "nonliteral-module-load",
message:
"packages/server/src/server/nonliteral-runtime-load.ts: nonliteral-module-load forbids <computed>",
},
]);
});
test("the AST guard follows createRequire factory origins and chained aliases", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"packages/server/src/server/named-create-require.ts",
'import { createRequire } from "node:module";\n' +
"const makeLoader = createRequire;\n" +
"const load = makeLoader(import.meta.url);\n" +
"void load(process.env.RUNTIME);\n",
);
await source(
root,
"packages/server/src/server/namespace-create-require.ts",
'import * as moduleApi from "node:module";\n' +
"const makeLoader = moduleApi.createRequire;\n" +
"const makeLoaderAlias = makeLoader;\n" +
"const load = makeLoaderAlias(import.meta.url);\n" +
"const loadAlias = load;\n" +
"void loadAlias(process.env.RUNTIME);\n" +
'const computedFactory = moduleApi["createRequire"];\n' +
"const computedLoad = computedFactory(import.meta.url);\n" +
"void computedLoad(process.env.RUNTIME);\n",
);
await source(
root,
"packages/server/src/server/commonjs-create-require.ts",
'const moduleApi = require("node:module");\n' +
"const makeLoader = moduleApi.createRequire;\n" +
"const makeLoaderAlias = makeLoader;\n" +
"const load = makeLoaderAlias(import.meta.url);\n" +
"const loadAlias = load;\n" +
"void loadAlias(process.env.RUNTIME);\n" +
"const computedFactory = moduleApi[`createRequire`];\n" +
"const computedLoad = computedFactory(import.meta.url);\n" +
"void computedLoad(process.env.RUNTIME);\n",
);
const violations = await findWorkspaceBoundaryViolations(root);
assert.equal(violations.length, 5);
assert.deepEqual(
violations.map(({ file, rule }) => ({ file, rule })),
[
{
file: "packages/server/src/server/commonjs-create-require.ts",
rule: "nonliteral-module-load",
},
{
file: "packages/server/src/server/commonjs-create-require.ts",
rule: "nonliteral-module-load",
},
{
file: "packages/server/src/server/named-create-require.ts",
rule: "nonliteral-module-load",
},
{
file: "packages/server/src/server/namespace-create-require.ts",
rule: "nonliteral-module-load",
},
{
file: "packages/server/src/server/namespace-create-require.ts",
rule: "nonliteral-module-load",
},
],
);
});
test("the AST guard follows direct createRequire property calls", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"packages/server/src/server/direct-create-require.ts",
'import * as moduleApi from "node:module";\n' +
"const loadA = moduleApi.createRequire(import.meta.url);\n" +
"void loadA(process.env.RUNTIME);\n" +
"\n" +
'const moduleObject = require("node:module");\n' +
"const loadB = moduleObject.createRequire(import.meta.url);\n" +
"void loadB(process.env.RUNTIME);\n" +
"\n" +
'const loadC = moduleApi["createRequire"](import.meta.url);\n' +
"void loadC(process.env.RUNTIME);\n" +
"\n" +
"const loadD = moduleApi[`createRequire`](import.meta.url);\n" +
"void loadD(process.env.RUNTIME);\n",
);
const violations = await findWorkspaceBoundaryViolations(root);
assert.equal(violations.length, 4);
assert.ok(violations.every(({ rule }) => rule === "nonliteral-module-load"));
});
test("audited production loader exceptions are narrow", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"packages/server/src/server/workspace-runtime/command/internal/command-runtime.ts",
'import { createRequire } from "node:module";\n' +
"function resolveRuntimeCommand(target) {\n" +
' const moduleRequire = createRequire("package.json");\n' +
" return moduleRequire.resolve(target);\n" +
"}\n" +
"function unreviewedCommandLoad(target) {\n" +
' const moduleRequire = createRequire("package.json");\n' +
" return moduleRequire(target);\n" +
"}\n",
);
await source(
root,
"packages/server/src/server/speech/providers/local/sherpa/sherpa-runtime-env.ts",
'import { createRequire } from "node:module";\n' +
"function resolveSherpaLoaderEnv(target) {\n" +
' const require = createRequire("package.json");\n' +
" return require.resolve(target);\n" +
"}\n",
);
await source(
root,
"packages/server/src/server/speech/providers/local/sherpa/sherpa-onnx-node-loader.ts",
"function loadWithRequire(requireFn: NodeRequire, target) {\n" +
" return requireFn(target);\n" +
"}\n",
);
assert.deepEqual(await findWorkspaceBoundaryViolations(root), [
{
file: "packages/server/src/server/workspace-runtime/command/internal/command-runtime.ts",
import: "<computed>",
rule: "nonliteral-module-load",
message:
"packages/server/src/server/workspace-runtime/command/internal/command-runtime.ts: nonliteral-module-load forbids <computed>",
},
]);
});
test("the boundary guard rejects a copied helper under any runtime filename", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"runtimes/fixture/src/innocent-name.mjs",
'const commands = ["fs-stat", "fs-list", "fs-read", "fs-write"]; void commands;\n',
);
assert.deepEqual(await findWorkspaceBoundaryViolations(root), [
{
file: "runtimes/fixture/src/innocent-name.mjs",
import: "workspace-helper protocol",
rule: "duplicate-workspace-helper",
message:
"runtimes/fixture/src/innocent-name.mjs: duplicate-workspace-helper forbids workspace-helper protocol",
},
]);
});
test("the boundary guard rejects a helper protocol split across runtime files", async (t) => {
const root = await fixtureRoot(t);
await source(
root,
"runtimes/fixture/src/read-commands.mjs",
'export const commands = ["fs-stat", "fs-list"];\n',
);
await source(
root,
"runtimes/fixture/src/write-commands.mjs",
'export const commands = ["fs-read", "fs-write"];\n',
);
assert.deepEqual(await findWorkspaceBoundaryViolations(root), [
{
file: "runtimes/fixture",
import: "workspace-helper protocol",
rule: "duplicate-workspace-helper",
message: "runtimes/fixture: duplicate-workspace-helper forbids workspace-helper protocol",
},
]);
});
test("the AST guard rejects every statically resolvable provider probe internal import", async (t) => {
const root = await fixtureRoot(t);
await source(
@@ -116,12 +430,16 @@ test("the AST guard rejects every statically resolvable provider probe internal
const violations = await findWorkspaceBoundaryViolations(root);
assert.equal(violations.length, 8);
assert.deepEqual(new Set(violations.map(({ rule }) => rule)), new Set(["module-entrypoint"]));
assert.deepEqual(
new Set(violations.map(({ rule }) => rule)),
new Set(["module-entrypoint", "nonliteral-module-load"]),
);
assert.deepEqual(
new Set(violations.map((violation) => violation.import)),
new Set([
"../provider-probe/internal/service.js",
"@getpaseo/server/provider-probe/internal/service.js",
"<computed>",
]),
);
});
@@ -150,7 +468,7 @@ test("owned integrations, explicit legacy code, and fixture contract imports pas
root,
"packages/server/src/server/workspace-runtime/internal/service.ts",
'import { git } from "../git-observation/internal/integration.js";\n' +
'import { helper } from "../../workspace-helper/internal/integration/index.js";\n' +
'import { helper } from "@getpaseo/workspace-helper";\n' +
"export const service = [git, helper];\n",
);
await source(
@@ -160,7 +478,7 @@ test("owned integrations, explicit legacy code, and fixture contract imports pas
);
await source(
root,
"packages/fixture-workspace-runtime/src/index.mjs",
"runtimes/fixture/src/index.mjs",
'import { CommandRuntimeControlSchema } from "@getpaseo/workspace-runtime-contract";\n' +
'import { spawn } from "node:child_process";\n' +
'import("./nested.mjs"); void CommandRuntimeControlSchema; void spawn;\n',
@@ -170,20 +488,12 @@ test("owned integrations, explicit legacy code, and fixture contract imports pas
"packages/server/src/server/workspace-runtime/git-observation/internal/integration.ts",
"export const git = 1;\n",
);
await source(
root,
"packages/server/src/server/workspace-helper/internal/integration/index.ts",
"export const helper = 1;\n",
);
await source(
root,
"packages/fixture-workspace-runtime/src/nested.mjs",
"export const nested = 1;\n",
);
await source(root, "packages/workspace-helper/src/index.ts", "export const helper = 1;\n");
await source(root, "runtimes/fixture/src/nested.mjs", "export const nested = 1;\n");
assert.deepEqual(await findWorkspaceBoundaryViolations(root), []);
try {
await run(oxlint, ["packages"], { cwd: root });
await run(oxlint, ["packages", "runtimes"], { cwd: root });
} catch (error) {
assert.fail(`${error.stdout ?? ""}${error.stderr ?? ""}`);
}
@@ -216,7 +526,7 @@ test("strict public schemas and helper argv reject root authority independent of
run(
process.execPath,
[
path.join(repoRoot, "packages/server/src/server/workspace-helper/executable.mjs"),
path.join(repoRoot, "packages/workspace-helper/src/executable.mjs"),
"fs-stat",
`--${key}`,
"/private",
@@ -249,3 +559,13 @@ async function source(root, relativePath, contents) {
await mkdir(path.dirname(filename), { recursive: true });
await writeFile(filename, contents);
}
async function collectRuntimeSources(directory) {
const entries = await readdir(directory, { recursive: true, withFileTypes: true });
const sources = await Promise.all(
entries
.filter((entry) => entry.isFile() && /\.(?:js|mjs|ts|tsx)$/u.test(entry.name))
.map((entry) => readFile(path.join(entry.parentPath, entry.name), "utf8")),
);
return sources.join("\n");
}
@@ -0,0 +1,103 @@
import { execFile } from "node:child_process";
import { mkdir, mkdtemp, rename, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
import assert from "node:assert/strict";
import { promisify } from "node:util";
const run = promisify(execFile);
const repoRoot = path.resolve(import.meta.dirname, "..");
test("the fixture installs and describes from isolated packed dependencies", async (t) => {
const root = await mkdtemp(path.join(tmpdir(), "paseo-runtime-fixture-standalone-"));
const managedArtifacts = [];
t.after(async () => {
for (const artifact of managedArtifacts) {
await rm(path.join(repoRoot, artifact.relativePath), { recursive: true, force: true });
}
for (const artifact of managedArtifacts) {
if (artifact.hiddenPath) {
await rename(artifact.hiddenPath, path.join(repoRoot, artifact.relativePath));
}
}
await rm(root, { recursive: true, force: true });
});
const packs = path.join(root, "packs");
await mkdir(packs);
for (const relativePath of buildArtifacts) {
const hiddenPath = path.join(root, "previous-dist", relativePath.replaceAll("/", "__"));
try {
await mkdir(path.dirname(hiddenPath), { recursive: true });
await rename(path.join(repoRoot, relativePath), hiddenPath);
managedArtifacts.push({ relativePath, hiddenPath });
} catch (error) {
if (error.code !== "ENOENT") throw error;
managedArtifacts.push({ relativePath, hiddenPath: null });
}
}
const packageRoots = {
contract: "packages/workspace-runtime-contract",
helper: "packages/workspace-helper",
fixture: "runtimes/fixture",
};
await run("npm", ["run", "build", "--workspace=@getpaseo/fixture-workspace-runtime"], {
cwd: repoRoot,
});
const tarballs = {};
for (const [name, relativeRoot] of Object.entries(packageRoots)) {
const result = JSON.parse(
(
await run("npm", ["pack", "--json", "--pack-destination", packs], {
cwd: path.join(repoRoot, relativeRoot),
})
).stdout,
);
tarballs[name] = path.join(packs, result[0].filename);
}
const project = path.join(root, "fixture");
await mkdir(project);
await writeFile(
path.join(project, "package.json"),
JSON.stringify({
private: true,
dependencies: {
"@getpaseo/workspace-runtime-contract": `file:${tarballs.contract}`,
"@getpaseo/workspace-helper": `file:${tarballs.helper}`,
"@getpaseo/fixture-workspace-runtime": `file:${tarballs.fixture}`,
},
}),
);
await run("npm", ["install", "--ignore-scripts"], {
cwd: project,
env: { ...process.env, npm_config_cache: path.join(root, "npm-cache") },
});
const bin = path.join(project, "node_modules/.bin/paseo-fixture-workspace-runtime");
const description = JSON.parse((await run(bin, ["describe"], { cwd: project })).stdout);
assert.deepEqual(description, {
protocolVersion: 1,
modes: ["pipes", "pty"],
reconcile: false,
});
const bundledHelper = path.join(
project,
"node_modules/@getpaseo/fixture-workspace-runtime/dist/paseo-workspace-helper",
);
assert.deepEqual(JSON.parse((await run(bundledHelper, ["describe"], { cwd: project })).stdout), {
protocolVersion: 1,
version: 1,
capabilities: ["files", "watch", "resolve-command"],
});
assert.match(
await import("node:fs/promises").then(({ realpath }) => realpath(bin)),
/node_modules\/@getpaseo\/fixture-workspace-runtime\//u,
);
});
const buildArtifacts = [
"packages/workspace-runtime-contract/dist",
"packages/workspace-helper/dist",
"runtimes/fixture/dist",
];