mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 15:30:43 +00:00
fix(cli): tighten Windows restart policy-close health checks
Preserve contributor credit and land the narrowed restart-health fix after ProjectClownfish review/follow-up.
This commit is contained in:
@@ -241,14 +241,60 @@ describe("inspectGatewayRestart", () => {
|
||||
expect(snapshot.staleGatewayPids).toEqual([]);
|
||||
});
|
||||
|
||||
it("treats auth-closed probe as healthy gateway reachability", async () => {
|
||||
const snapshot = await inspectAmbiguousOwnershipWithProbe({
|
||||
ok: false,
|
||||
close: { code: 1008, reason: "auth required" },
|
||||
});
|
||||
it.each([
|
||||
"auth required",
|
||||
"owner auth required",
|
||||
"connect failed",
|
||||
"device required",
|
||||
"pairing required",
|
||||
"pairing required: device is asking for more scopes than currently approved",
|
||||
"unauthorized: gateway token missing (set gateway.remote.token to match gateway.auth.token)",
|
||||
"unauthorized: gateway password mismatch (set gateway.remote.password to match gateway.auth.password)",
|
||||
"unauthorized: device token rejected (pair/repair this device, or provide gateway token)",
|
||||
])(
|
||||
"treats local policy-close probe reason %s as healthy gateway reachability",
|
||||
async (reason) => {
|
||||
const snapshot = await inspectAmbiguousOwnershipWithProbe({
|
||||
ok: false,
|
||||
close: { code: 1008, reason },
|
||||
});
|
||||
|
||||
expect(snapshot.healthy).toBe(true);
|
||||
});
|
||||
expect(snapshot.healthy).toBe(true);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
"",
|
||||
" ",
|
||||
"repair required",
|
||||
"repairing required",
|
||||
"unpairing required",
|
||||
"device",
|
||||
"device required by local spoof",
|
||||
"device required: identity missing",
|
||||
"device identity required",
|
||||
"connect challenge missing nonce",
|
||||
"connect challenge timeout",
|
||||
"authoritative policy close",
|
||||
"device identity mismatch",
|
||||
"device signature invalid",
|
||||
"device nonce required",
|
||||
"token expired",
|
||||
"password required",
|
||||
"missing scope: operator.admin",
|
||||
"role denied",
|
||||
"unauthorized: session revoked",
|
||||
])(
|
||||
"does not treat ambiguous 1008 close reason %s as healthy gateway reachability",
|
||||
async (reason) => {
|
||||
const snapshot = await inspectAmbiguousOwnershipWithProbe({
|
||||
ok: false,
|
||||
close: { code: 1008, reason },
|
||||
});
|
||||
|
||||
expect(snapshot.healthy).toBe(false);
|
||||
},
|
||||
);
|
||||
|
||||
it("requires the expected gateway version when provided", async () => {
|
||||
probeGateway.mockResolvedValue({
|
||||
|
||||
@@ -83,12 +83,33 @@ function looksLikeAuthClose(code: number | undefined, reason: string | undefined
|
||||
return false;
|
||||
}
|
||||
const normalized = normalizeLowercaseStringOrEmpty(reason);
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
// The restart probe runs against loopback only and only decides restart
|
||||
// liveness, not authorization. Keep this allowlist exact so a local listener
|
||||
// cannot satisfy the health check with broad device/auth-looking text.
|
||||
return (
|
||||
normalized.includes("auth") ||
|
||||
normalized.includes("token") ||
|
||||
normalized.includes("password") ||
|
||||
normalized.includes("scope") ||
|
||||
normalized.includes("role")
|
||||
normalized === "auth required" ||
|
||||
normalized === "owner auth required" ||
|
||||
normalized === "connect failed" ||
|
||||
normalized === "device required" ||
|
||||
normalized === "pairing required" ||
|
||||
normalized.startsWith("pairing required:") ||
|
||||
normalized.startsWith("unauthorized: gateway token missing") ||
|
||||
normalized.startsWith("unauthorized: gateway token mismatch") ||
|
||||
normalized.startsWith("unauthorized: gateway token not configured") ||
|
||||
normalized.startsWith("unauthorized: gateway password missing") ||
|
||||
normalized.startsWith("unauthorized: gateway password mismatch") ||
|
||||
normalized.startsWith("unauthorized: gateway password not configured") ||
|
||||
normalized.startsWith("unauthorized: bootstrap token invalid or expired") ||
|
||||
normalized.startsWith("unauthorized: tailscale identity missing") ||
|
||||
normalized.startsWith("unauthorized: tailscale proxy headers missing") ||
|
||||
normalized.startsWith("unauthorized: tailscale identity check failed") ||
|
||||
normalized.startsWith("unauthorized: tailscale identity mismatch") ||
|
||||
normalized.startsWith("unauthorized: too many failed authentication attempts") ||
|
||||
normalized.startsWith("unauthorized: device token mismatch") ||
|
||||
normalized.startsWith("unauthorized: device token rejected")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user