diff --git a/src/gateway/server.auth.control-ui.suite.ts b/src/gateway/server.auth.control-ui.suite.ts index 5480a15211a..bc2048bb856 100644 --- a/src/gateway/server.auth.control-ui.suite.ts +++ b/src/gateway/server.auth.control-ui.suite.ts @@ -3,7 +3,6 @@ import path from "node:path"; import { expect, test, vi } from "vitest"; import { WebSocket } from "ws"; import { - approvePendingPairingIfNeeded, BACKEND_GATEWAY_CLIENT, connectReq, configureTrustedProxyControlUiAuth, @@ -136,14 +135,6 @@ export function registerControlUiAndPairingSuite(): void { }; }; - const startServerWithOperatorIdentity = async (identityPrefix = "openclaw-device-scope-") => { - const { server, ws, port, prevToken } = await startServerWithClient("secret", { - controlUiEnabled: true, - }); - const { identityPath, identity, client } = await createOperatorIdentityFixture(identityPrefix); - return { server, ws, port, prevToken, identityPath, identity, client }; - }; - const startControlUiServerWithOperatorIdentity = async ( identityPrefix = "openclaw-device-scope-", ) => { @@ -219,17 +210,19 @@ export function registerControlUiAndPairingSuite(): void { clientMode: string; displayName: string; platform: string; + scopes?: string[]; }): Promise<{ identityPath: string; identity: { deviceId: string } }> => { const { publicKeyRawBase64UrlFromPem } = await import("../infra/device-identity.js"); const { approveDevicePairing, requestDevicePairing } = await import("../infra/device-pairing.js"); const { identityPath, identity } = await createOperatorIdentityFixture(params.identityPrefix); + const scopes = params.scopes ?? ["operator.read"]; const devicePublicKey = publicKeyRawBase64UrlFromPem(identity.publicKeyPem); const seeded = await requestDevicePairing({ deviceId: identity.deviceId, publicKey: devicePublicKey, role: "operator", - scopes: ["operator.read"], + scopes, clientId: params.clientId, clientMode: params.clientMode, displayName: params.displayName, @@ -491,9 +484,6 @@ export function registerControlUiAndPairingSuite(): void { const scopedHealth = await rpcReq(scopedWs, "health"); expect(scopedHealth.ok).toBe(true); - - const talk = await rpcReq(scopedWs, "chat.history", { sessionKey: "main", limit: 1 }); - expect(talk.ok).toBe(true); scopedWs.close(); }); } finally { @@ -1269,36 +1259,26 @@ export function registerControlUiAndPairingSuite(): void { test("allows operator.read connect when device is paired with operator.admin", async () => { const { listDevicePairing } = await import("../infra/device-pairing.js"); - const { server, ws, port, prevToken, identityPath, identity, client } = - await startServerWithOperatorIdentity(); - - const initialNonce = await readConnectChallengeNonce(ws); - const initial = await connectReq(ws, { - token: "secret", + const { identityPath, identity } = await seedApprovedOperatorReadPairing({ + identityPrefix: "openclaw-device-admin-superset-", + clientId: TEST_OPERATOR_CLIENT.id, + clientMode: TEST_OPERATOR_CLIENT.mode, + displayName: "operator-admin-superset", + platform: TEST_OPERATOR_CLIENT.platform, scopes: ["operator.admin"], - client, - device: await buildSignedDeviceForIdentity({ - identityPath, - client, - scopes: ["operator.admin"], - nonce: initialNonce, - }), }); - if (!initial.ok) { - await approvePendingPairingIfNeeded(); - } - ws.close(); + const { server, port, prevToken } = await startControlUiServer("secret"); const ws2 = await openWs(port); const nonce2 = await readConnectChallengeNonce(ws2); const res = await connectReq(ws2, { token: "secret", scopes: ["operator.read"], - client, + client: TEST_OPERATOR_CLIENT, device: await buildSignedDeviceForIdentity({ identityPath, - client, + client: TEST_OPERATOR_CLIENT, scopes: ["operator.read"], nonce: nonce2, }), @@ -1562,38 +1542,6 @@ export function registerControlUiAndPairingSuite(): void { } }); - test("allows gateway backend clients on loopback even with a remote-looking host header", async () => { - const { server, port, prevToken } = await startControlUiServer("secret"); - const wsRemoteLike = await openWs(port, { host: "gateway.example" }); - try { - const remoteLikeBackend = await connectReq(wsRemoteLike, { - token: "secret", - client: BACKEND_GATEWAY_CLIENT, - }); - expect(remoteLikeBackend.ok).toBe(true); - } finally { - wsRemoteLike.close(); - await server.close(); - restoreGatewayToken(prevToken); - } - }); - - test("allows gateway backend clients on loopback with a private host header", async () => { - const { server, port, prevToken } = await startControlUiServer("secret"); - const wsPrivateHost = await openWs(port, { host: "172.17.0.2:18789" }); - try { - const remoteLikeBackend = await connectReq(wsPrivateHost, { - token: "secret", - client: BACKEND_GATEWAY_CLIENT, - }); - expect(remoteLikeBackend.ok).toBe(true); - } finally { - wsPrivateHost.close(); - await server.close(); - restoreGatewayToken(prevToken); - } - }); - test("allows CLI clients on loopback even when the host header is not private-or-loopback", async () => { const { server, port, prevToken } = await startControlUiServer("secret"); const wsRemoteLike = await openWs(port, { host: "gateway.example" });