




















@@ -19,6 +19,8 @@ function escapeRegex(value: string): string {
1919return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
2020}
212122+const secretKeyPattern = /^[a-f0-9]{64}$/u;
23+2224describe("scripts/lib/openclaw-test-state", () => {
2325it("creates a sourceable env file and JSON description", async () => {
2426const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-state-script-"));
@@ -47,12 +49,14 @@ describe("scripts/lib/openclaw-test-state", () => {
4749expect(payload.stateDir).toBe(path.join(payload.home, ".openclaw"));
4850expect(payload.configPath).toBe(path.join(payload.stateDir, "openclaw.json"));
4951expect(payload.workspaceDir).toBe(path.join(payload.home, "workspace"));
52+expect(payload.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY).toMatch(secretKeyPattern);
5053expect(payload.env).toEqual({
5154HOME: payload.home,
5255USERPROFILE: payload.home,
5356OPENCLAW_HOME: payload.home,
5457OPENCLAW_STATE_DIR: payload.stateDir,
5558OPENCLAW_CONFIG_PATH: payload.configPath,
59+OPENCLAW_AUTH_PROFILE_SECRET_KEY: payload.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,
5660});
5761expect(payload.config).toEqual({
5862update: {
@@ -66,14 +70,16 @@ describe("scripts/lib/openclaw-test-state", () => {
6670expect(envFileText).toContain("export OPENCLAW_HOME=");
6771expect(envFileText).toContain("export OPENCLAW_STATE_DIR=");
6872expect(envFileText).toContain("export OPENCLAW_CONFIG_PATH=");
73+expect(envFileText).toContain("export OPENCLAW_AUTH_PROFILE_SECRET_KEY=");
69747075const probe = await execFileAsync("bash", [
7176"-lc",
72-`source ${shellQuote(envFile)}; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,stateDir:process.env.OPENCLAW_STATE_DIR,channel:config.update.channel}));'`,
77+`source ${shellQuote(envFile)}; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,stateDir:process.env.OPENCLAW_STATE_DIR,secretKey:process.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,channel:config.update.channel}));'`,
7378]);
7479expect(JSON.parse(probe.stdout)).toEqual({
7580home: payload.home,
7681stateDir: payload.stateDir,
82+secretKey: payload.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,
7783channel: "stable",
7884});
7985await fs.rm(payload.root, { recursive: true, force: true });
@@ -106,7 +112,7 @@ describe("scripts/lib/openclaw-test-state", () => {
106112107113const probe = await execFileAsync("bash", [
108114"-lc",
109-`source ${shellQuote(snippetFile)}; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,openclawHome:process.env.OPENCLAW_HOME,workspace:process.env.OPENCLAW_TEST_WORKSPACE_DIR,channel:config.update.channel}));'; rm -rf "$HOME"`,
115+`source ${shellQuote(snippetFile)}; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,openclawHome:process.env.OPENCLAW_HOME,workspace:process.env.OPENCLAW_TEST_WORKSPACE_DIR,secretKey:process.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,channel:config.update.channel}));'; rm -rf "$HOME"`,
110116]);
111117112118const payload = JSON.parse(probe.stdout);
@@ -116,6 +122,7 @@ describe("scripts/lib/openclaw-test-state", () => {
116122);
117123expect(payload.openclawHome).toBe(payload.home);
118124expect(payload.workspace).toBe(`${payload.home}/workspace`);
125+expect(payload.secretKey).toMatch(secretKeyPattern);
119126expect(payload.channel).toBe("stable");
120127121128const customTemp = path.join(tempRoot, "state-tmp");
@@ -135,6 +142,52 @@ describe("scripts/lib/openclaw-test-state", () => {
135142}
136143});
137144145+it("keeps shell key generation independent of node", async () => {
146+const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-state-path-node-"));
147+const fakeBin = path.join(tempRoot, "bin");
148+const snippetFile = path.join(tempRoot, "state.sh");
149+const functionFile = path.join(tempRoot, "state-function.sh");
150+try {
151+await fs.mkdir(fakeBin, { recursive: true });
152+await fs.writeFile(
153+path.join(fakeBin, "node"),
154+"#!/bin/sh\necho 'fake node should not be used for key generation' >&2\nexit 42\n",
155+"utf8",
156+);
157+await fs.chmod(path.join(fakeBin, "node"), 0o755);
158+159+const shell = await execFileAsync(process.execPath, [
160+scriptPath,
161+"shell",
162+"--label",
163+"path-node",
164+"--scenario",
165+"empty",
166+]);
167+await fs.writeFile(snippetFile, shell.stdout, "utf8");
168+169+const shellProbe = await execFileAsync("bash", [
170+"-lc",
171+`export PATH=${shellQuote(fakeBin)}:$PATH; source ${shellQuote(snippetFile)}; printf '%s' "$OPENCLAW_AUTH_PROFILE_SECRET_KEY"; rm -rf "$HOME"`,
172+]);
173+expect(shellProbe.stdout).toMatch(secretKeyPattern);
174+175+const renderedFunction = await execFileAsync(process.execPath, [
176+scriptPath,
177+"shell-function",
178+]);
179+await fs.writeFile(functionFile, renderedFunction.stdout, "utf8");
180+181+const functionProbe = await execFileAsync("bash", [
182+"-lc",
183+`export PATH=${shellQuote(fakeBin)}:$PATH; export OPENCLAW_TEST_STATE_TMPDIR=${shellQuote(path.join(tempRoot, "function-tmp"))}; source ${shellQuote(functionFile)}; openclaw_test_state_create "path node" minimal; printf '%s' "$OPENCLAW_AUTH_PROFILE_SECRET_KEY"; rm -rf "$HOME"`,
184+]);
185+expect(functionProbe.stdout).toMatch(secretKeyPattern);
186+} finally {
187+await fs.rm(tempRoot, { recursive: true, force: true });
188+}
189+});
190+138191it("creates the upgrade survivor scenario", async () => {
139192const { stdout } = await execFileAsync(process.execPath, [
140193scriptPath,
@@ -182,24 +235,26 @@ describe("scripts/lib/openclaw-test-state", () => {
182235183236const probe = await execFileAsync("bash", [
184237"-lc",
185-`export OPENCLAW_TEST_STATE_TMPDIR=${shellQuote(path.join(tempRoot, "function-tmp"))}; source ${shellQuote(snippetFile)}; export OPENCLAW_AGENT_DIR=/tmp/outside-agent; openclaw_test_state_create "onboard case" minimal; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,tmpDir:process.env.OPENCLAW_TEST_STATE_TMPDIR,agentDir:process.env.OPENCLAW_AGENT_DIR || null,workspace:process.env.OPENCLAW_TEST_WORKSPACE_DIR,config}));'; rm -rf "$HOME"`,
238+`export OPENCLAW_TEST_STATE_TMPDIR=${shellQuote(path.join(tempRoot, "function-tmp"))}; source ${shellQuote(snippetFile)}; export OPENCLAW_AGENT_DIR=/tmp/outside-agent; openclaw_test_state_create "onboard case" minimal; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,tmpDir:process.env.OPENCLAW_TEST_STATE_TMPDIR,agentDir:process.env.OPENCLAW_AGENT_DIR || null,workspace:process.env.OPENCLAW_TEST_WORKSPACE_DIR,secretKey:process.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,config}));'; rm -rf "$HOME"`,
186239]);
187240188241const payload = JSON.parse(probe.stdout);
189242expect(payload.home).toBe(`${payload.tmpDir}/${path.basename(payload.home)}`);
190243expect(payload.home).toContain("/openclaw-onboard-case-minimal-home.");
191244expect(payload.agentDir).toBeNull();
192245expect(payload.workspace).toBe(`${payload.home}/workspace`);
246+expect(payload.secretKey).toMatch(secretKeyPattern);
193247expect(payload.config).toStrictEqual({});
194248195249const existingHome = path.join(tempRoot, "existing-home");
196250const existingProbe = await execFileAsync("bash", [
197251"-lc",
198-`source ${shellQuote(snippetFile)}; openclaw_test_state_create ${shellQuote(existingHome)} minimal; printf '{"kept":true}\\n' > "$OPENCLAW_CONFIG_PATH"; openclaw_test_state_create ${shellQuote(existingHome)} empty; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,config}));'`,
252+`source ${shellQuote(snippetFile)}; openclaw_test_state_create ${shellQuote(existingHome)} minimal; firstKey="$OPENCLAW_AUTH_PROFILE_SECRET_KEY"; export firstKey; printf '{"kept":true}\\n' > "$OPENCLAW_CONFIG_PATH"; openclaw_test_state_create ${shellQuote(existingHome)} empty; node -e 'const fs=require("node:fs"); const config=JSON.parse(fs.readFileSync(process.env.OPENCLAW_CONFIG_PATH,"utf8")); process.stdout.write(JSON.stringify({home:process.env.HOME,secretKey:process.env.OPENCLAW_AUTH_PROFILE_SECRET_KEY,firstKey:process.env.firstKey,config}));'`,
199253]);
200254201255const existingPayload = JSON.parse(existingProbe.stdout);
202256expect(existingPayload.home).toBe(existingHome);
257+expect(existingPayload.secretKey).toBe(existingPayload.firstKey);
203258expect(existingPayload.config).toEqual({ kept: true });
204259} finally {
205260await fs.rm(tempRoot, { recursive: true, force: true });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。