ui: make web gateway client role/scopes configurable

This commit is contained in:
nzhu 2026-01-29 10:42:06 +08:00
parent 7ad2ee3af5
commit 614aabfa22
2 changed files with 17 additions and 3 deletions

View File

@ -4,6 +4,7 @@ import { loadNodes } from "./controllers/nodes";
import { loadAgents } from "./controllers/agents";
import type { GatewayEventFrame, GatewayHelloOk } from "./gateway";
import { GatewayBrowserClient } from "./gateway";
import { GATEWAY_CLIENT_NAMES } from "../../../src/gateway/protocol/client-info.js";
import type { EventLogEntry } from "./app-events";
import type { AgentsListResult, PresenceEntry, HealthSnapshot, StatusSummary } from "./types";
import type { Tab } from "./navigation";
@ -116,11 +117,14 @@ export function connectGateway(host: GatewayHost) {
host.execApprovalError = null;
host.client?.stop();
const clientName =
host.tab === "public-chat" ? GATEWAY_CLIENT_NAMES.WEBCHAT_UI : "moltbot-control-ui";
host.client = new GatewayBrowserClient({
url: host.settings.gatewayUrl,
token: host.settings.token.trim() ? host.settings.token : undefined,
password: host.password.trim() ? host.password : undefined,
clientName: "moltbot-control-ui",
clientName,
mode: "webchat",
onHello: (hello) => {
host.connected = true;

View File

@ -53,6 +53,15 @@ export type GatewayBrowserClientOptions = {
platform?: string;
mode?: GatewayClientMode;
instanceId?: string;
/**
* Gateway role/scopes for this client.
* Control UI defaults to operator + admin scopes.
* Public WebChat will override this in a follow-up PR once the gateway enforces role allowlists.
*/
role?: string;
scopes?: string[];
onHello?: (hello: GatewayHelloOk) => void;
onEvent?: (evt: GatewayEventFrame) => void;
onClose?: (info: { code: number; reason: string }) => void;
@ -132,8 +141,9 @@ export class GatewayBrowserClient {
// Gateways may reject this unless gateway.controlUi.allowInsecureAuth is enabled.
const isSecureContext = typeof crypto !== "undefined" && !!crypto.subtle;
const scopes = ["operator.admin", "operator.approvals", "operator.pairing"];
const role = "operator";
const scopes =
this.opts.scopes ?? ["operator.admin", "operator.approvals", "operator.pairing"];
const role = this.opts.role ?? "operator";
let deviceIdentity: Awaited<ReturnType<typeof loadOrCreateDeviceIdentity>> | null = null;
let canFallbackToShared = false;
let authToken = this.opts.token;