@downcity/agent 1.1.283 → 1.1.285

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,68 +0,0 @@
1
- /**
2
- * @file 验证 Linux Bubblewrap 参数对统一 Sandbox 策略的映射。
3
- */
4
-
5
- import test from "node:test";
6
- import assert from "node:assert/strict";
7
- import fs from "node:fs/promises";
8
- import os from "node:os";
9
- import path from "node:path";
10
-
11
- import { build_linux_bubblewrap_args } from "@downcity/shell/sandbox/backends/LinuxBubblewrap.js";
12
-
13
- function has_option_pair(args, option, source_path, target_path = source_path) {
14
- for (let index = 0; index < args.length - 2; index += 1) {
15
- if (
16
- args[index] === option &&
17
- args[index + 1] === source_path &&
18
- args[index + 2] === target_path
19
- ) return true;
20
- }
21
- return false;
22
- }
23
-
24
- test("Linux maps read paths to ro-bind and workspace to bind", async () => {
25
- const fixture_root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-bwrap-"));
26
- try {
27
- const project_root = path.join(fixture_root, "project");
28
- const tool_root = path.join(fixture_root, "tool");
29
- await fs.mkdir(project_root, { recursive: true });
30
- await fs.mkdir(tool_root, { recursive: true });
31
- const request = {
32
- execution_id: "sh_test",
33
- execution_dir: path.join(project_root, ".downcity", "shell", "sh_test"),
34
- cmd: "printf hello",
35
- cwd: project_root,
36
- shell_path: "/bin/sh",
37
- login: true,
38
- base_env: { PATH: "/usr/bin:/bin" },
39
- policy: {
40
- backend: "linux-bubblewrap",
41
- root_path: project_root,
42
- sandbox_dir: path.join(project_root, ".downcity", "sandbox"),
43
- home_dir: path.join(project_root, ".downcity", "sandbox"),
44
- tmp_dir: path.join(project_root, ".downcity", "sandbox", "tmp"),
45
- cache_dir: path.join(project_root, ".downcity", "sandbox", ".cache"),
46
- env_allowlist: ["PATH"],
47
- read_only_paths: [tool_root],
48
- read_write_paths: [project_root],
49
- network_mode: "off",
50
- fingerprint: "policy_test",
51
- },
52
- };
53
- const args = build_linux_bubblewrap_args(request);
54
- assert.equal(args.includes("--unshare-net"), true);
55
- assert.equal(has_option_pair(args, "--ro-bind", tool_root), true);
56
- assert.equal(has_option_pair(args, "--bind", tool_root), false);
57
- assert.equal(has_option_pair(args, "--bind", project_root), true);
58
- assert.deepEqual(args.slice(-5), [
59
- "--chdir",
60
- project_root,
61
- "/bin/sh",
62
- "-lc",
63
- "printf hello",
64
- ]);
65
- } finally {
66
- await fs.rm(fixture_root, { recursive: true, force: true });
67
- }
68
- });
@@ -1,80 +0,0 @@
1
- /**
2
- * @file 验证 Safe Sandbox 环境变量收敛与临时目录映射。
3
- */
4
-
5
- import test from "node:test";
6
- import assert from "node:assert/strict";
7
- import path from "node:path";
8
-
9
- import { build_macos_sandbox_env } from "@downcity/shell/sandbox/backends/MacOsSeatbelt.js";
10
- import { build_linux_sandbox_env } from "@downcity/shell/sandbox/backends/LinuxBubblewrap.js";
11
- import { resolve_sandbox_policy } from "@downcity/shell/sandbox/SandboxPolicy.js";
12
-
13
- function create_request() {
14
- const root_path = "/tmp/downcity-shell-env/project";
15
- const sandbox_dir = path.join(root_path, ".downcity", "sandbox");
16
- return {
17
- execution_id: "sh_test",
18
- execution_dir: path.join(root_path, ".downcity", "shell", "sh_test"),
19
- cmd: "printf hello",
20
- cwd: root_path,
21
- shell_path: "/bin/zsh",
22
- login: true,
23
- base_env: {
24
- PATH: "/usr/bin:/bin",
25
- LANG: "C.UTF-8",
26
- DC_SESSION_ID: "session_test",
27
- },
28
- policy: {
29
- backend: "macos-seatbelt",
30
- root_path,
31
- sandbox_dir,
32
- home_dir: sandbox_dir,
33
- tmp_dir: path.join(sandbox_dir, "tmp"),
34
- cache_dir: path.join(sandbox_dir, ".cache"),
35
- env_allowlist: ["PATH", "LANG"],
36
- read_only_paths: ["/usr", "/bin"],
37
- read_write_paths: [root_path],
38
- network_mode: "full",
39
- fingerprint: "policy_test",
40
- },
41
- };
42
- }
43
-
44
- function assert_sandbox_tmp_env(env, tmp_dir) {
45
- assert.equal(env.TMPDIR, tmp_dir);
46
- assert.equal(env.TMP, tmp_dir);
47
- assert.equal(env.TEMP, tmp_dir);
48
- assert.equal(env.TEMPDIR, tmp_dir);
49
- assert.equal(env.TMPPREFIX, path.join(tmp_dir, "zsh"));
50
- assert.equal(env.DC_SANDBOX_TMP, tmp_dir);
51
- }
52
-
53
- test("macOS safe env points temporary variables at sandbox tmp", () => {
54
- const request = create_request();
55
- const env = build_macos_sandbox_env(request);
56
- assert_sandbox_tmp_env(env, request.policy.tmp_dir);
57
- });
58
-
59
- test("Linux safe env points temporary variables at sandbox tmp", () => {
60
- const request = create_request();
61
- const env = build_linux_sandbox_env({
62
- ...request,
63
- policy: { ...request.policy, backend: "linux-bubblewrap" },
64
- });
65
- assert_sandbox_tmp_env(env, request.policy.tmp_dir);
66
- });
67
-
68
- test("safe policy exports explicit agent env keys only", async () => {
69
- const policy = await resolve_sandbox_policy({
70
- rootPath: "/tmp/downcity-shell-env/project",
71
- env: {
72
- DYNAMIC_ENV_REPRO: "dynamic_value",
73
- DC_DYNAMIC_REPRO: "dc_value",
74
- },
75
- }, {});
76
- assert.equal(policy.env_allowlist.includes("PATH"), true);
77
- assert.equal(policy.env_allowlist.includes("DYNAMIC_ENV_REPRO"), true);
78
- assert.equal(policy.env_allowlist.includes("DC_DYNAMIC_REPRO"), true);
79
- assert.equal(policy.env_allowlist.includes("HOST_ONLY_ENV_REPRO"), false);
80
- });
@@ -1,157 +0,0 @@
1
- /**
2
- * @file 验证 shell sandbox 启动前依赖诊断。
3
- *
4
- * 关键点(中文)
5
- * - 测试编译后的 bin 输出,避免测试文件进入 package 源码导出面。
6
- * - 通过注入探针模拟 Linux 依赖状态,不要求当前测试机安装 bwrap。
7
- */
8
-
9
- import test from "node:test";
10
- import assert from "node:assert/strict";
11
-
12
- import {
13
- checkShellSandboxPreflightWithProbe,
14
- } from "@downcity/shell/sandbox/SandboxPreflight.js";
15
-
16
- async function withPlatform(platform, callback) {
17
- const previous = Object.getOwnPropertyDescriptor(process, "platform");
18
- Object.defineProperty(process, "platform", {
19
- configurable: true,
20
- value: platform,
21
- });
22
- try {
23
- return await callback();
24
- } finally {
25
- if (previous) {
26
- Object.defineProperty(process, "platform", previous);
27
- }
28
- }
29
- }
30
-
31
- function createProbe(params) {
32
- return {
33
- commandExists: async (command) => params.commands?.has(command) === true,
34
- readProcInt: async (filePath) => params.proc?.get(filePath) ?? null,
35
- inspectWindowsMxcSupport: async () => params.windows_support || {
36
- supported: true,
37
- windows_build: 26100,
38
- isolation_tier: "appcontainer-dacl",
39
- warnings: [],
40
- },
41
- };
42
- }
43
-
44
- test("Linux shell sandbox preflight reports missing bwrap and disabled userns", async () => {
45
- await withPlatform("linux", async () => {
46
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
47
- commands: new Set(),
48
- proc: new Map([
49
- ["/proc/sys/kernel/unprivileged_userns_clone", 0],
50
- ["/proc/sys/user/max_user_namespaces", 0],
51
- ]),
52
- }));
53
-
54
- assert.equal(result.ok, false);
55
- assert.equal(result.backend, "linux-bubblewrap");
56
- assert.deepEqual(
57
- result.issues.map((issue) => issue.code),
58
- ["missing-command", "userns-disabled"],
59
- );
60
- assert.match(result.issues[0].message, /bubblewrap/);
61
- assert.match(result.issues[1].message, /user namespaces/);
62
- });
63
- });
64
-
65
- test("Linux shell sandbox preflight accepts bwrap with enabled userns", async () => {
66
- await withPlatform("linux", async () => {
67
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
68
- commands: new Set(["bwrap"]),
69
- proc: new Map([
70
- ["/proc/sys/kernel/unprivileged_userns_clone", 1],
71
- ["/proc/sys/user/max_user_namespaces", 1024],
72
- ]),
73
- }));
74
-
75
- assert.equal(result.ok, true);
76
- assert.equal(result.backend, "linux-bubblewrap");
77
- assert.deepEqual(result.issues, []);
78
- });
79
- });
80
-
81
- test("Windows MXC development sandbox accepts a supported runtime", async () => {
82
- await withPlatform("win32", async () => {
83
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
84
- commands: new Set(["cmd.exe"]),
85
- proc: new Map(),
86
- }));
87
-
88
- assert.equal(result.ok, true);
89
- assert.equal(result.backend, "windows-mxc-dev");
90
- assert.deepEqual(result.issues, []);
91
- });
92
- });
93
-
94
- test("Windows MXC development sandbox reports a missing cmd.exe", async () => {
95
- await withPlatform("win32", async () => {
96
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
97
- commands: new Set(),
98
- proc: new Map(),
99
- }));
100
-
101
- assert.equal(result.ok, false);
102
- assert.equal(result.backend, "windows-mxc-dev");
103
- assert.deepEqual(result.issues.map((issue) => issue.code), ["missing-command"]);
104
- });
105
- });
106
-
107
- test("Windows MXC development sandbox rejects hosts older than 24H2", async () => {
108
- await withPlatform("win32", async () => {
109
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
110
- commands: new Set(["cmd.exe"]),
111
- proc: new Map(),
112
- windows_support: {
113
- supported: false,
114
- windows_build: 22631,
115
- warnings: [],
116
- reason: "Windows 11 24H2 is required.",
117
- },
118
- }));
119
-
120
- assert.equal(result.ok, false);
121
- assert.deepEqual(result.issues.map((issue) => issue.code), [
122
- "unsupported-windows-version",
123
- ]);
124
- });
125
- });
126
-
127
- test("Windows MXC development sandbox rejects an unavailable runtime", async () => {
128
- await withPlatform("win32", async () => {
129
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
130
- commands: new Set(["cmd.exe"]),
131
- proc: new Map(),
132
- windows_support: {
133
- supported: false,
134
- windows_build: 26100,
135
- warnings: [],
136
- reason: "MXC probe failed.",
137
- },
138
- }));
139
-
140
- assert.equal(result.ok, false);
141
- assert.deepEqual(result.issues.map((issue) => issue.code), [
142
- "sandbox-runtime-unavailable",
143
- ]);
144
- });
145
- });
146
-
147
- test("Other unsupported platforms still fail shell sandbox preflight", async () => {
148
- await withPlatform("freebsd", async () => {
149
- const result = await checkShellSandboxPreflightWithProbe(createProbe({
150
- commands: new Set(),
151
- proc: new Map(),
152
- }));
153
-
154
- assert.equal(result.ok, false);
155
- assert.deepEqual(result.issues.map((issue) => issue.code), ["unsupported-platform"]);
156
- });
157
- });