惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
J
Java Code Geeks
G
Google Developers Blog
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
Vercel News
Vercel News
S
SegmentFault 最新的问题
Engineering at Meta
Engineering at Meta
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
Y
Y Combinator Blog
博客园_首页
Last Week in AI
Last Week in AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
A
About on SuperTechFans
B
Blog
Microsoft Security Blog
Microsoft Security Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: require service identity for update handoffs · openc...
shakkernerd · 2026-06-11 · via Recent Commits to openclaw:main

@@ -139,7 +139,10 @@ vi.mock("../../infra/update-managed-service-handoff.js", () => ({

139139

? `openclaw update --yes --timeout ${Math.ceil(params.timeoutMs / 1000)}`

140140

: "openclaw update --yes",

141141

buildManagedServiceHandoffUnavailableMessage: (command: string) =>

142-

`Run \`${command}\` from a shell outside the gateway service.`,

142+

[

143+

"OpenClaw updates cannot safely run inside the live gateway process without a managed-service handoff.",

144+

`Run \`${command}\` from a shell outside the gateway service, or restart/update from the host UI.`,

145+

].join("\n"),

143146

}));

144147145148

vi.mock("./validation.js", () => ({

@@ -219,6 +222,33 @@ function firstMockCall(

219222

return call;

220223

}

221224225+

async function withProcessEnv<T>(

226+

updates: Record<string, string | undefined>,

227+

run: () => Promise<T>,

228+

): Promise<T> {

229+

const previous = new Map<string, string | undefined>();

230+

for (const key of Object.keys(updates)) {

231+

previous.set(key, process.env[key]);

232+

const value = updates[key];

233+

if (value === undefined) {

234+

delete process.env[key];

235+

} else {

236+

process.env[key] = value;

237+

}

238+

}

239+

try {

240+

return await run();

241+

} finally {

242+

for (const [key, value] of previous) {

243+

if (value === undefined) {

244+

delete process.env[key];

245+

} else {

246+

process.env[key] = value;

247+

}

248+

}

249+

}

250+

}

251+222252

function mockGlobalInstallSurface() {

223253

resolveUpdateInstallSurfaceMock.mockResolvedValueOnce({

224254

kind: "global",

@@ -365,7 +395,9 @@ describe("update.run restart scheduling", () => {

365395

detectRespawnSupervisorMock.mockReturnValueOnce("launchd");

366396

mockGlobalInstallSurface();

367397368-

const payload = await captureUpdateRunPayload();

398+

const payload = await withProcessEnv({ OPENCLAW_LAUNCHD_LABEL: "ai.openclaw.gateway" }, () =>

399+

captureUpdateRunPayload(),

400+

);

369401370402

expect(runGatewayUpdateMock).not.toHaveBeenCalled();

371403

expect(startManagedServiceUpdateHandoffMock).toHaveBeenCalledTimes(1);

@@ -427,7 +459,9 @@ describe("update.run restart scheduling", () => {

427459

detectRespawnSupervisorMock.mockReturnValueOnce("systemd");

428460

mockGlobalInstallSurface();

429461430-

await invokeUpdateRun({ restartDelayMs: 0 });

462+

await withProcessEnv({ OPENCLAW_SYSTEMD_UNIT: "openclaw-gateway.service" }, () =>

463+

invokeUpdateRun({ restartDelayMs: 0 }),

464+

);

431465432466

expect(startManagedServiceUpdateHandoffMock).toHaveBeenCalledWith(

433467

expect.objectContaining({

@@ -452,7 +486,9 @@ describe("update.run restart scheduling", () => {

452486

throw Object.assign(new Error("uv_cwd"), { code: "ENOENT", syscall: "uv_cwd" });

453487

});

454488

try {

455-

await invokeUpdateRun({});

489+

await withProcessEnv({ OPENCLAW_LAUNCHD_LABEL: "ai.openclaw.gateway" }, () =>

490+

invokeUpdateRun({}),

491+

);

456492

} finally {

457493

cwdSpy.mockRestore();

458494

}

@@ -468,19 +504,9 @@ describe("update.run restart scheduling", () => {

468504

it("hands supervised git/dev updates to the CLI path instead of rebuilding live dist in-process", async () => {

469505

detectRespawnSupervisorMock.mockReturnValueOnce("launchd");

470506

mockGitInstallSurface("/tmp/openclaw-git");

471-

const previousLaunchdLabel = process.env.OPENCLAW_LAUNCHD_LABEL;

472-

process.env.OPENCLAW_LAUNCHD_LABEL = "ai.openclaw.gateway";

473-474-

let payload: UpdateRunPayload | undefined;

475-

try {

476-

payload = await captureUpdateRunPayload();

477-

} finally {

478-

if (previousLaunchdLabel === undefined) {

479-

delete process.env.OPENCLAW_LAUNCHD_LABEL;

480-

} else {

481-

process.env.OPENCLAW_LAUNCHD_LABEL = previousLaunchdLabel;

482-

}

483-

}

507+

const payload = await withProcessEnv({ OPENCLAW_LAUNCHD_LABEL: "ai.openclaw.gateway" }, () =>

508+

captureUpdateRunPayload(),

509+

);

484510485511

expect(runGatewayUpdateMock).not.toHaveBeenCalled();

486512

expect(startManagedServiceUpdateHandoffMock).toHaveBeenCalledTimes(1);

@@ -528,29 +554,17 @@ describe("update.run restart scheduling", () => {

528554

expect(readCapturedPayload().status).toBe("ok");

529555

});

530556531-

it("hands systemd-supervised git/dev updates to handoff from systemd markers", async () => {

532-

const previousSystemdUnit = process.env.OPENCLAW_SYSTEMD_UNIT;

533-

const previousInvocationId = process.env.INVOCATION_ID;

534-

delete process.env.OPENCLAW_SYSTEMD_UNIT;

535-

process.env.INVOCATION_ID = "8a77e69a8f604bf0b7984879b9f17a7c";

557+

it("hands systemd-supervised git/dev updates to handoff from the durable unit identity", async () => {

536558

detectRespawnSupervisorMock.mockReturnValueOnce("systemd");

537559

mockGitInstallSurface("/tmp/openclaw-git");

538560539-

let payload: UpdateRunPayload | undefined;

540-

try {

541-

payload = await captureUpdateRunPayload();

542-

} finally {

543-

if (previousSystemdUnit === undefined) {

544-

delete process.env.OPENCLAW_SYSTEMD_UNIT;

545-

} else {

546-

process.env.OPENCLAW_SYSTEMD_UNIT = previousSystemdUnit;

547-

}

548-

if (previousInvocationId === undefined) {

549-

delete process.env.INVOCATION_ID;

550-

} else {

551-

process.env.INVOCATION_ID = previousInvocationId;

552-

}

553-

}

561+

const payload = await withProcessEnv(

562+

{

563+

OPENCLAW_SYSTEMD_UNIT: "openclaw-gateway.service",

564+

INVOCATION_ID: "8a77e69a8f604bf0b7984879b9f17a7c",

565+

},

566+

() => captureUpdateRunPayload(),

567+

);

554568555569

expect(runGatewayUpdateMock).not.toHaveBeenCalled();

556570

expect(startManagedServiceUpdateHandoffMock).toHaveBeenCalledTimes(1);

@@ -567,6 +581,29 @@ describe("update.run restart scheduling", () => {

567581

expect(payload?.handoff?.status).toBe("started");

568582

});

569583584+

it("does not hand off systemd-supervised git/dev updates from generic systemd markers alone", async () => {

585+

detectRespawnSupervisorMock.mockReturnValueOnce("systemd");

586+

mockGitInstallSurface("/tmp/openclaw-git");

587+588+

const payload = await withProcessEnv(

589+

{

590+

OPENCLAW_SYSTEMD_UNIT: undefined,

591+

INVOCATION_ID: "8a77e69a8f604bf0b7984879b9f17a7c",

592+

},

593+

() => captureUpdateRunPayload(),

594+

);

595+596+

expect(runGatewayUpdateMock).not.toHaveBeenCalled();

597+

expect(startManagedServiceUpdateHandoffMock).not.toHaveBeenCalled();

598+

expect(scheduleGatewaySigusr1RestartMock).not.toHaveBeenCalled();

599+

expect(payload?.ok).toBe(false);

600+

expect(payload?.restart).toBeNull();

601+

expect(payload?.result?.status).toBe("skipped");

602+

expect(payload?.result?.reason).toBe("managed-service-handoff-unavailable");

603+

expect(payload?.result?.mode).toBe("git");

604+

expect(payload?.handoff?.status).toBe("unavailable");

605+

});

606+570607

it("returns a safe command when package updates cannot be handed off", async () => {

571608

mockGlobalInstallSurface();

572609

@@ -583,7 +620,8 @@ describe("update.run restart scheduling", () => {

583620

status: "unavailable",

584621

command: "openclaw update --yes --timeout 1800",

585622

message:

586-

"Run `openclaw update --yes --timeout 1800` from a shell outside the gateway service.",

623+

"OpenClaw updates cannot safely run inside the live gateway process without a managed-service handoff.\n" +

624+

"Run `openclaw update --yes --timeout 1800` from a shell outside the gateway service, or restart/update from the host UI.",

587625

});

588626

});

589627