import { realpath } from "node:fs/promises"; import path from "node:path"; /** Registration may name the workbench through its guest alias. Only that * outer alias is permitted: resources and each checkout remain physical, * directly contained directories. Persist the resulting root-relative path. */ export async function managedResourcePath(workbench: string, directory: string): Promise { const root = await realpath(workbench); const selected = path.resolve(root, directory); const name = path.basename(selected); const resources = path.dirname(selected); if (path.basename(resources) !== "resources" || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) throw new Error(`Repository is outside the managed workbench: ${directory}`); const relative = `resources/${name}`; if ((await realpath(path.dirname(resources))) !== root || (await realpath(selected)) !== path.join(root, relative)) throw new Error(`Managed repository path crosses a symlink or escapes the workbench: ${directory}`); return relative; }