fix(hub): enable tenant Typst package resolution

This commit is contained in:
2026-07-22 17:47:56 +08:00
parent 6462e42823
commit 36660f72d6
6 changed files with 156 additions and 45 deletions
+25 -1
View File
@@ -33,6 +33,8 @@ const SAFE_HOST_ENV_KEYS = [
"all_proxy",
"no_proxy",
"NODE_USE_ENV_PROXY",
"TYPST_PACKAGE_PATH",
"TYPST_PACKAGE_CACHE_PATH",
] as const;
const SANDBOX_HIDDEN_ENV_KEYS = [
@@ -134,6 +136,7 @@ export async function createAgentSecurityPolicy(input: AgentSecurityInput): Prom
const sensitiveReadPaths = hostSensitiveReadPaths(hostEnv);
const runtimeReadPaths = hostRuntimeReadPaths(hostEnv);
const typstCacheWritePaths = hostTypstCacheWritePaths(hostEnv);
const selectedSkills = input.skills ?? [];
const skillPlugin = selectedSkills.length === 0
? null
@@ -174,7 +177,7 @@ export async function createAgentSecurityPolicy(input: AgentSecurityInput): Prom
autoAllowBashIfSandboxed: true,
allowUnsandboxedCommands: false,
filesystem: {
allowWrite: [workspaceDir],
allowWrite: [...new Set([workspaceDir, ...typstCacheWritePaths])],
// Reject every write path by default, then re-open only the canonical
// workspace. This prevents bubblewrap's ordinary temp exceptions from
// turning an unauthorized path into a successful ephemeral write.
@@ -244,9 +247,30 @@ function hostRuntimeReadPaths(env: Readonly<Record<string, string | undefined>>)
if (!isAbsolute(cphBin)) throw new Error("CPH_BIN must be absolute for the Agent subprocess");
platformPaths.push(resolve(cphBin));
}
platformPaths.push(...configuredTypstPackagePaths(env, ["TYPST_PACKAGE_PATH", "TYPST_PACKAGE_CACHE_PATH"]));
return [...new Set(platformPaths.map((path) => resolve(path)))];
}
function hostTypstCacheWritePaths(env: Readonly<Record<string, string | undefined>>): string[] {
return configuredTypstPackagePaths(env, ["TYPST_PACKAGE_CACHE_PATH"]);
}
function configuredTypstPackagePaths(
env: Readonly<Record<string, string | undefined>>,
names: readonly ("TYPST_PACKAGE_PATH" | "TYPST_PACKAGE_CACHE_PATH")[],
): string[] {
const paths: string[] = [];
for (const name of names) {
const packagePath = env[name]?.trim();
if (packagePath === undefined || packagePath === "") continue;
if (!isAbsolute(packagePath)) throw new Error(`${name} must be absolute for the Agent subprocess`);
const canonical = resolve(packagePath);
if (canonical === "/") throw new Error(`${name} must not be the filesystem root`);
paths.push(canonical);
}
return paths;
}
function hostSensitiveReadPaths(env: Readonly<Record<string, string | undefined>>): string[] {
const home = homedir();
const paths = [