Gateway UX: harden remote ws guidance and onboarding defaults

This commit is contained in:
Brian Mendonca
2026-02-22 03:39:56 -07:00
committed by Peter Steinberger
parent 6fda04e938
commit 8a3d04c19c
8 changed files with 169 additions and 7 deletions

View File

@@ -334,6 +334,8 @@ describe("buildGatewayConnectionDetails", () => {
expect((thrown as Error).message).toContain("SECURITY ERROR");
expect((thrown as Error).message).toContain("plaintext ws://");
expect((thrown as Error).message).toContain("wss://");
expect((thrown as Error).message).toContain("Tailscale Serve/Funnel");
expect((thrown as Error).message).toContain("openclaw doctor --fix");
});
it("allows ws:// for loopback addresses in local mode", () => {

View File

@@ -149,7 +149,12 @@ export function buildGatewayConnectionDetails(
"Both credentials and chat data would be exposed to network interception.",
`Source: ${urlSource}`,
`Config: ${configPath}`,
"Fix: Use wss:// for the gateway URL, or connect via SSH tunnel to localhost.",
"Fix: Use wss:// for remote gateway URLs.",
"Safe remote access defaults:",
"- keep gateway.bind=loopback and use an SSH tunnel (ssh -N -L 18789:127.0.0.1:18789 user@gateway-host)",
"- or use Tailscale Serve/Funnel for HTTPS remote access",
"Doctor: openclaw doctor --fix",
"Docs: https://docs.openclaw.ai/gateway/remote",
].join("\n"),
);
}

View File

@@ -130,6 +130,9 @@ describe("GatewayClient security checks", () => {
message: expect.stringContaining("SECURITY ERROR"),
}),
);
const error = onConnectError.mock.calls[0]?.[0] as Error;
expect(error.message).toContain("openclaw doctor --fix");
expect(error.message).toContain("Tailscale Serve/Funnel");
expect(wsInstances.length).toBe(0); // No WebSocket created
client.stop();
});
@@ -149,6 +152,8 @@ describe("GatewayClient security checks", () => {
message: expect.stringContaining("SECURITY ERROR"),
}),
);
const error = onConnectError.mock.calls[0]?.[0] as Error;
expect(error.message).toContain("openclaw doctor --fix");
expect(wsInstances.length).toBe(0); // No WebSocket created
client.stop();
});

View File

@@ -126,7 +126,9 @@ export class GatewayClient {
const error = new Error(
`SECURITY ERROR: Cannot connect to "${displayHost}" over plaintext ws://. ` +
"Both credentials and chat data would be exposed to network interception. " +
"Use wss:// for the gateway URL, or connect via SSH tunnel to localhost.",
"Use wss:// for remote URLs. Safe defaults: keep gateway.bind=loopback and connect via SSH tunnel " +
"(ssh -N -L 18789:127.0.0.1:18789 user@gateway-host), or use Tailscale Serve/Funnel. " +
"Run `openclaw doctor --fix` for guidance.",
);
this.opts.onConnectError?.(error);
return;