docs/docs/uk/web/control-ui.md
2026-04-27 09:33:58 +00:00

44 KiB
Raw Blame History

read_when sidebarTitle summary title x-i18n
Ви хочете керувати Gateway з браузера
Ви хочете доступ Tailnet без SSH-тунелів
Control UI Контрольний UI на основі браузера для Gateway (чат, Node, конфігурація) Контрольний UI
generated_at model provider source_hash source_path workflow
2026-04-27T09:31:19Z gpt-5.4 openai 062128bc66e63b768f4088a935a8850ce3c61e6c431ee5ef0567e5a93d579878 web/control-ui.md 15

Контрольний UI — це невеликий односторінковий застосунок Vite + Lit, який обслуговується Gateway:

  • за замовчуванням: http://<host>:18789/
  • необов’язковий префікс: задайте gateway.controlUi.basePath (наприклад, /openclaw)

Він взаємодіє безпосередньо з WebSocket Gateway на тому самому порту.

Швидке відкриття (локально)

Якщо Gateway запущено на тому самому комп’ютері, відкрийте:

Якщо сторінка не завантажується, спочатку запустіть Gateway: openclaw gateway.

Автентифікація передається під час рукостискання WebSocket через:

  • connect.params.auth.token
  • connect.params.auth.password
  • заголовки ідентичності Tailscale Serve, коли gateway.auth.allowTailscale: true
  • заголовки ідентичності trusted-proxy, коли gateway.auth.mode: "trusted-proxy"

Панель налаштувань на інформаційній панелі зберігає токен для поточної сесії вкладки браузера та вибрану URL-адресу gateway; паролі не зберігаються. Під час онбордингу зазвичай створюється токен gateway для автентифікації за спільним секретом при першому підключенні, але автентифікація паролем також працює, коли gateway.auth.mode має значення "password".

Спарювання пристрою (перше підключення)

Коли ви підключаєтеся до Control UI з нового браузера або пристрою, Gateway зазвичай вимагає одноразове схвалення спарювання. Це захід безпеки для запобігання несанкціонованому доступу.

Що ви побачите: "disconnected (1008): pairing required"

```bash openclaw devices list ``` ```bash openclaw devices approve ```

Якщо браузер повторно намагається пройти спарювання зі зміненими даними автентифікації (роль/області доступу/публічний ключ), попередній запит, що очікує, замінюється, і створюється новий requestId. Перед схваленням знову виконайте openclaw devices list.

Якщо браузер уже спарений і ви змінюєте його з доступу лише для читання на доступ для запису/адміністратора, це розглядається як підвищення рівня схвалення, а не як тихе повторне підключення. OpenClaw залишає попереднє схвалення активним, блокує повторне підключення з ширшими правами й просить вас явно схвалити новий набір областей доступу.

Після схвалення пристрій запам’ятовується й не вимагатиме повторного схвалення, доки ви не відкличете його через openclaw devices revoke --device <id> --role <role>. Див. Devices CLI щодо ротації токенів і відкликання.

- Прямі локальні браузерні підключення через local loopback (`127.0.0.1` / `localhost`) схвалюються автоматично. - Tailscale Serve може пропустити цикл спарювання для операторських сесій Control UI, коли `gateway.auth.allowTailscale: true`, ідентичність Tailscale перевірено, а браузер надає ідентичність свого пристрою. - Прямі прив’язки Tailnet, браузерні LAN-підключення та профілі браузера без ідентичності пристрою все одно потребують явного схвалення. - Кожен профіль браузера генерує унікальний ID пристрою, тому зміна браузера або очищення даних браузера потребуватиме повторного спарювання.

Особиста ідентичність (локально в браузері)

Control UI підтримує особисту ідентичність для кожного браузера (відображуване ім’я та аватар), яка додається до вихідних повідомлень для атрибуції у спільних сесіях. Вона зберігається в сховищі браузера, прив’язана до поточного профілю браузера й не синхронізується з іншими пристроями та не зберігається на сервері поза звичайними метаданими авторства в транскрипті для повідомлень, які ви фактично надсилаєте. Очищення даних сайту або перехід до іншого браузера скидає її до порожнього значення.

Той самий локальний для браузера шаблон застосовується до перевизначення аватара асистента. Завантажені аватари асистента накладаються на ідентичність, визначену gateway, лише в локальному браузері й ніколи не проходять назад через config.patch. Спільне поле конфігурації ui.assistant.avatar усе ще доступне для клієнтів без UI, які записують це поле безпосередньо (наприклад, скриптових gateway або користувацьких панелей).

Кінцева точка конфігурації під час виконання

Control UI отримує свої налаштування під час виконання з /__openclaw/control-ui-config.json. Доступ до цієї кінцевої точки захищено тією самою автентифікацією gateway, що й решта HTTP-поверхні: неавтентифіковані браузери не можуть її отримати, а успішне отримання вимагає або вже дійсного токена/пароля gateway, або ідентичності Tailscale Serve, або ідентичності trusted-proxy.

Підтримка мов

Control UI може локалізуватися під час першого завантаження на основі локалі вашого браузера. Щоб перевизначити її пізніше, відкрийте Overview -> Gateway Access -> Language. Перемикач локалі знаходиться в картці Gateway Access, а не в розділі Appearance.

  • Підтримувані локалі: en, zh-CN, zh-TW, pt-BR, de, es, ja-JP, ko, fr, tr, uk, id, pl, th
  • Неанглійські переклади ліниво завантажуються в браузері.
  • Вибрана локаль зберігається в сховищі браузера та повторно використовується під час наступних відвідувань.
  • Відсутні ключі перекладу повертаються до англійської.

Що він уміє (сьогодні)

- Спілкування з моделлю через Gateway WS (`chat.history`, `chat.send`, `chat.abort`, `chat.inject`). - Розмова з OpenAI Realtime безпосередньо з браузера через WebRTC. Gateway створює короткоживучий клієнтський секрет Realtime через `talk.realtime.session`; браузер надсилає аудіо з мікрофона безпосередньо до OpenAI і передає виклики інструмента `openclaw_agent_consult` назад через `chat.send` для більшої налаштованої моделі OpenClaw. - Потокова передача викликів інструментів + картки живого виводу інструментів у чаті (події агента). - Канали: вбудовані канали плюс bundled/external plugin channels, статус, вхід через QR і конфігурація для кожного каналу (`channels.status`, `web.login.*`, `config.patch`). - Екземпляри: список присутності + оновлення (`system-presence`). - Сесії: список + перевизначення моделі/thinking/fast/verbose/trace/reasoning для кожної сесії (`sessions.list`, `sessions.patch`). - Dreaming: статус Dreaming, перемикач увімкнення/вимкнення та читач Dream Diary (`doctor.memory.status`, `doctor.memory.dreamDiary`, `config.patch`). - Завдання Cron: список/додавання/редагування/запуск/увімкнення/вимкнення + історія запусків (`cron.*`). - Skills: статус, увімкнення/вимкнення, встановлення, оновлення ключів API (`skills.*`). - Node: список + обмеження (`node.list`). - Схвалення exec: редагування списків дозволів gateway або node + політика запиту для `exec host=gateway/node` (`exec.approvals.*`). - Перегляд/редагування `~/.openclaw/openclaw.json` (`config.get`, `config.set`). - Застосування + перезапуск із валідацією (`config.apply`) і пробудження останньої активної сесії. - Записи включають захист base-hash, щоб запобігти перезапису паралельних змін. - Записи (`config.set`/`config.apply`/`config.patch`) попередньо перевіряють активне розв’язання SecretRef для посилань у надісланому корисному навантаженні конфігурації; нерозв’язані активні надіслані посилання відхиляються до запису. - Рендеринг схеми + форми (`config.schema` / `config.schema.lookup`, включно з полями `title` / `description`, відповідними підказками UI, зведеннями безпосередніх дочірніх елементів, метаданими документації для вузлів вкладених об’єктів/wildcard/масивів/композицій, а також схемами плагінів + каналів, коли вони доступні); редактор Raw JSON доступний лише тоді, коли знімок підтримує безпечне сире проходження туди й назад. - Якщо знімок не може безпечно пройти сирий цикл туди й назад, Control UI примусово вмикає режим Form і вимикає режим Raw для цього знімка. - У редакторі Raw JSON команда "Reset to saved" зберігає форму, написану в сирому вигляді (форматування, коментарі, розкладку `$include`), замість повторного рендерингу сплющеного знімка, тож зовнішні редагування переживають скидання, якщо знімок може безпечно пройти сирий цикл. - Структуровані значення об’єктів SecretRef відображаються в текстових полях форми лише для читання, щоб запобігти випадковому пошкодженню через перетворення об’єкта на рядок. - Налагодження: знімки status/health/models + журнал подій + ручні RPC-виклики (`status`, `health`, `models.list`). - Журнали: живий tail файлових журналів gateway з фільтрацією/експортом (`logs.tail`). - Оновлення: запуск оновлення пакета/git + перезапуск (`update.run`) зі звітом про перезапуск, потім опитування `update.status` після повторного підключення для перевірки версії запущеного gateway. - Для ізольованих завдань способом доставки за замовчуванням є announce summary. Ви можете перемкнути на none, якщо потрібні лише внутрішні запуски. - Поля channel/target з’являються, коли вибрано announce. - Режим Webhook використовує `delivery.mode = "webhook"` із `delivery.to`, установленим у дійсну HTTP(S) URL-адресу Webhook. - Для завдань основної сесії доступні режими доставки webhook і none. - Розширені елементи керування редагуванням включають delete-after-run, clear agent override, точні/зі зсувом параметри cron, перевизначення agent model/thinking і best-effort перемикачі доставки. - Валідація форми виконується вбудовано з помилками на рівні полів; некоректні значення вимикають кнопку збереження, доки помилки не буде виправлено. - Установіть `cron.webhookToken`, щоб надсилати окремий bearer-токен; якщо не вказано, webhook надсилається без заголовка автентифікації. - Застарілий резервний варіант: збережені застарілі завдання з `notify: true` усе ще можуть використовувати `cron.webhook`, доки їх не буде мігровано.

Поведінка чату

- `chat.send` є **неблокувальним**: він одразу підтверджує запит із `{ runId, status: "started" }`, а відповідь передається потоком через події `chat`. - Завантаження чату приймають зображення плюс файли, що не є відео. Зображення зберігають нативний шлях до зображення; інші файли зберігаються як керовані медіа й показуються в історії як посилання на вкладення. - Повторне надсилання з тим самим `idempotencyKey` повертає `{ status: "in_flight" }` під час виконання і `{ status: "ok" }` після завершення. - Відповіді `chat.history` обмежуються за розміром для безпеки UI. Коли записи транскрипту надто великі, Gateway може обрізати довгі текстові поля, пропускати важкі блоки метаданих і замінювати надто великі повідомлення заповнювачем (`[chat.history omitted: message too large]`). - Зображення асистента/згенеровані зображення зберігаються як посилання на керовані медіа та повертаються через автентифіковані медіа-URL Gateway, тож перезавантаження не залежать від збереження сирих base64-пакетів зображень у відповіді історії чату. - `chat.history` також видаляє вбудовані теги директив лише для відображення з видимого тексту асистента (наприклад, `reply_to_*` і `audio_as_voice`), XML-пакети викликів інструментів у звичайному тексті (включно з `...`, `...`, `...`, `...` і обрізаними блоками викликів інструментів), а також витеклі ASCII/повноширинні токени керування моделлю, і пропускає записи асистента, весь видимий текст яких складається лише з точного тихого токена `NO_REPLY` / `no_reply`. - Під час активного надсилання та остаточного оновлення історії подання чату зберігає локальні оптимістичні повідомлення користувача/асистента видимими, якщо `chat.history` тимчасово повертає старіший знімок; канонічний транскрипт замінює ці локальні повідомлення, щойно історія Gateway наздоганяє. - `chat.inject` додає примітку асистента до транскрипту сесії й транслює подію `chat` для оновлень лише в UI (без запуску агента, без доставки в канал). - Перемикачі моделі й thinking у заголовку чату негайно виправляють активну сесію через `sessions.patch`; це сталі перевизначення сесії, а не опції надсилання лише на один хід. - Коли свіжі звіти Gateway про використання сесії показують високий тиск контексту, область створення повідомлення в чаті показує повідомлення про контекст, а на рекомендованих рівнях Compaction — кнопку compact, яка запускає звичайний шлях Compaction сесії. Застарілі знімки токенів приховуються, доки Gateway знову не повідомить про свіже використання. Режим розмови використовує зареєстрований провайдер голосу в реальному часі, який підтримує браузерні WebRTC-сесії. Налаштуйте OpenAI через `talk.provider: "openai"` разом із `talk.providers.openai.apiKey`, або повторно використайте конфігурацію Realtime-провайдера Voice Call. Браузер ніколи не отримує стандартний API-ключ OpenAI; він отримує лише ефемерний клієнтський секрет Realtime. Голос у реальному часі Google Live підтримується для внутрішнього Voice Call і мостів Google Meet, але ще не для цього браузерного шляху WebRTC. Промпт сесії Realtime збирається Gateway; `talk.realtime.session` не приймає перевизначення інструкцій від викликувача.
У редакторі чату елемент керування Talk — це кнопка з хвилями поруч із кнопкою диктування через мікрофон. Коли Talk запускається, у рядку стану редактора відображається `Connecting Talk...`, потім `Talk live`, поки аудіо підключено, або `Asking OpenClaw...`, поки виклик інструмента в реальному часі звертається до налаштованої більшої моделі через `chat.send`.
- Натисніть **Stop** (викликає `chat.abort`). - Поки виконання активне, звичайні подальші повідомлення стають у чергу. Натисніть **Steer** на повідомленні в черзі, щоб вставити це подальше повідомлення в поточний хід. - Введіть `/stop` (або окремі фрази переривання, як-от `stop`, `stop action`, `stop run`, `stop openclaw`, `please stop`), щоб перервати поза основним потоком. - `chat.abort` підтримує `{ sessionKey }` (без `runId`), щоб перервати всі активні виконання для цієї сесії. - Коли виконання переривається, частковий текст асистента все одно може відображатися в UI. - Gateway зберігає частковий текст асистента, перерваний під час виконання, в історії транскрипту, якщо існує буферизований вивід. - Збережені записи містять метадані переривання, щоб споживачі транскрипту могли відрізнити часткові результати переривання від звичайного завершеного виводу.

Встановлення PWA і web push

Control UI постачається з manifest.webmanifest і service worker, тому сучасні браузери можуть встановлювати його як окремий PWA. Web Push дає змогу Gateway пробуджувати встановлений PWA сповіщеннями, навіть коли вкладка або вікно браузера не відкриті.

Поверхня Що вона робить
ui/public/manifest.webmanifest Маніфест PWA. Браузери пропонують "Install app", щойно він стає доступним.
ui/public/sw.js Service worker, який обробляє події push і натискання на сповіщення.
push/vapid-keys.json (у каталозі стану OpenClaw) Автоматично згенерована пара ключів VAPID, що використовується для підпису payload Web Push.
push/web-push-subscriptions.json Збережені кінцеві точки підписок браузера.

Перевизначайте пару ключів VAPID через змінні середовища в процесі Gateway, якщо хочете зафіксувати ключі (для розгортань на кількох хостах, ротації секретів або тестів):

  • OPENCLAW_VAPID_PUBLIC_KEY
  • OPENCLAW_VAPID_PRIVATE_KEY
  • OPENCLAW_VAPID_SUBJECT (за замовчуванням mailto:openclaw@localhost)

Control UI використовує такі методи Gateway, обмежені областями доступу, щоб реєструвати й тестувати підписки браузера:

  • push.web.vapidPublicKey — отримує активний публічний ключ VAPID.
  • push.web.subscribe — реєструє endpoint разом із keys.p256dh/keys.auth.
  • push.web.unsubscribe — видаляє зареєстровану кінцеву точку.
  • push.web.test — надсилає тестове сповіщення до підписки викликувача.
Web Push не залежить від шляху ретрансляції iOS APNS (див. [Конфігурація](/uk/gateway/configuration) щодо push через relay) і наявного методу `push.test`, які націлені на нативне спарювання мобільних пристроїв.

Вбудовані розміщені елементи

Повідомлення асистента можуть відображати розміщений вебвміст вбудовано через шорткод [embed ...]. Політика sandbox для iframe керується через gateway.controlUi.embedSandbox:

Вимикає виконання скриптів усередині розміщених вбудованих елементів. Дозволяє інтерактивні вбудовані елементи, зберігаючи ізоляцію походження; це значення за замовчуванням і зазвичай його достатньо для самодостатніх браузерних ігор/віджетів. Додає `allow-same-origin` поверх `allow-scripts` для документів того самого сайту, яким навмисно потрібні ширші привілеї.

Приклад:

{
  gateway: {
    controlUi: {
      embedSandbox: "scripts",
    },
  },
}
Використовуйте `trusted` лише тоді, коли вбудованому документу справді потрібна поведінка того самого походження. Для більшості ігор і інтерактивних полотен, згенерованих агентом, безпечнішим вибором є `scripts`.

Абсолютні зовнішні URL-адреси вбудованих елементів http(s) залишаються заблокованими за замовчуванням. Якщо ви навмисно хочете, щоб [embed url="https://..."] завантажував сторонні сторінки, встановіть gateway.controlUi.allowExternalEmbedUrls: true.

Доступ Tailnet (рекомендовано)

Залиште Gateway на loopback і дозвольте Tailscale Serve проксіювати його через HTTPS:
```bash
openclaw gateway --tailscale serve
```

Відкрийте:

- `https://<magicdns>/` (або налаштований вами `gateway.controlUi.basePath`)

За замовчуванням запити Control UI/WebSocket Serve можуть автентифікуватися через заголовки ідентичності Tailscale (`tailscale-user-login`), коли `gateway.auth.allowTailscale` має значення `true`. OpenClaw перевіряє ідентичність, визначаючи адресу `x-forwarded-for` через `tailscale whois` і звіряючи її із заголовком, і приймає це лише тоді, коли запит потрапляє в loopback із заголовками Tailscale `x-forwarded-*`. Для операторських сесій Control UI з ідентичністю пристрою браузера цей перевірений шлях Serve також пропускає цикл спарювання пристрою; браузери без ідентичності пристрою та підключення з роллю node усе одно проходять звичайні перевірки пристрою. Установіть `gateway.auth.allowTailscale: false`, якщо хочете вимагати явні облікові дані зі спільним секретом навіть для трафіку Serve. Тоді використовуйте `gateway.auth.mode: "token"` або `"password"`.

Для цього асинхронного шляху ідентичності Serve невдалі спроби автентифікації для тієї самої IP-адреси клієнта та тієї самої області автентифікації серіалізуються перед записами обмеження швидкості. Тому одночасні невдалі повторні спроби з того самого браузера можуть показати `retry later` у другому запиті замість двох звичайних невідповідностей, що змагаються паралельно.

<Warning>
Автентифікація Serve без токена припускає, що хост gateway є довіреним. Якщо на цьому хості може виконуватися недовірений локальний код, вимагайте автентифікацію токеном/паролем.
</Warning>
```bash openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)" ```
Потім відкрийте:

- `http://<tailscale-ip>:18789/` (або налаштований вами `gateway.controlUi.basePath`)

Вставте відповідний спільний секрет у налаштування UI (він надсилається як `connect.params.auth.token` або `connect.params.auth.password`).

Небезпечний HTTP

Якщо ви відкриваєте панель через звичайний HTTP (http://<lan-ip> або http://<tailscale-ip>), браузер працює в незахищеному контексті й блокує WebCrypto. За замовчуванням OpenClaw блокує підключення Control UI без ідентичності пристрою.

Задокументовані винятки:

  • сумісність із незахищеним HTTP лише для localhost з gateway.controlUi.allowInsecureAuth=true
  • успішна операторська автентифікація Control UI через gateway.auth.mode: "trusted-proxy"
  • аварійний варіант gateway.controlUi.dangerouslyDisableDeviceAuth=true

Рекомендоване виправлення: використовуйте HTTPS (Tailscale Serve) або відкривайте UI локально:

  • https://<magicdns>/ (Serve)
  • http://127.0.0.1:18789/ (на хості gateway)
```json5 { gateway: { controlUi: { allowInsecureAuth: true }, bind: "tailnet", auth: { mode: "token", token: "replace-me" }, }, } ```
`allowInsecureAuth` — це лише локальний перемикач сумісності:

- Він дозволяє сесіям Control UI на localhost продовжувати роботу без ідентичності пристрою в незахищених HTTP-контекстах.
- Він не обходить перевірки спарювання.
- Він не послаблює вимоги до ідентичності пристрою для віддалених (не localhost) підключень.
```json5 { gateway: { controlUi: { dangerouslyDisableDeviceAuth: true }, bind: "tailnet", auth: { mode: "token", token: "replace-me" }, }, } ```
<Warning>
`dangerouslyDisableDeviceAuth` вимикає перевірки ідентичності пристрою в Control UI і є серйозним погіршенням безпеки. Поверніть налаштування назад якомога швидше після аварійного використання.
</Warning>
- Успішна автентифікація trusted-proxy може допустити **операторські** сесії Control UI без ідентичності пристрою. - Це **не** поширюється на сесії Control UI з роллю node. - Реверс-проксі на тому самому хості через loopback усе одно не задовольняють автентифікацію trusted-proxy; див. [Автентифікація trusted proxy](/uk/gateway/trusted-proxy-auth).

Див. Tailscale для вказівок щодо налаштування HTTPS.

Політика безпеки вмісту

Control UI постачається зі суворою політикою img-src: дозволені лише ресурси того самого походження, URL data: і локально згенеровані URL blob:. Віддалені URL-адреси http(s) і URL-адреси з відносним протоколом відхиляються браузером і не виконують мережевих запитів.

Що це означає на практиці:

  • Аватари та зображення, що обслуговуються за відносними шляхами (наприклад, /avatars/<id>), усе одно відображаються, включно з автентифікованими маршрутами аватарів, які UI отримує та перетворює на локальні URL blob:.
  • Вбудовані URL data:image/... усе одно відображаються (це корисно для payload у межах протоколу).
  • Локальні URL blob:, створені Control UI, усе одно відображаються.
  • Віддалені URL аватарів, які надходять із метаданих каналу, видаляються в допоміжних функціях аватарів Control UI і замінюються вбудованим логотипом/значком, тож скомпрометований або зловмисний канал не може примусити браузер оператора виконувати довільні віддалені запити зображень.

Щоб отримати цю поведінку, нічого змінювати не потрібно — вона завжди ввімкнена й не налаштовується.

Автентифікація маршруту аватара

Коли налаштовано автентифікацію gateway, кінцева точка аватара Control UI вимагає той самий токен gateway, що й решта API:

  • GET /avatar/<agentId> повертає зображення аватара лише автентифікованим викликувачам. GET /avatar/<agentId>?meta=1 повертає метадані аватара за тим самим правилом.
  • Неавтентифіковані запити до будь-якого з цих маршрутів відхиляються (аналогічно до сусіднього маршруту assistant-media). Це запобігає витоку ідентичності агента через маршрут аватара на хостах, які загалом захищені.
  • Сам Control UI пересилає токен gateway як bearer-заголовок під час отримання аватарів і використовує автентифіковані blob URL, тому зображення все одно відображається в панелях.

Якщо ви вимкнете автентифікацію gateway (не рекомендовано на спільних хостах), маршрут аватара також стане неавтентифікованим, узгоджуючись із рештою gateway.

Збирання UI

Gateway обслуговує статичні файли з dist/control-ui. Зберіть їх командою:

pnpm ui:build

Необов’язкова абсолютна база (коли потрібні фіксовані URL ресурсів):

OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build

Для локальної розробки (окремий dev server):

pnpm ui:dev

Потім укажіть UI URL WebSocket вашого Gateway (наприклад, ws://127.0.0.1:18789).

Налагодження/тестування: dev server + віддалений Gateway

Control UI — це статичні файли; ціль WebSocket налаштовується й може відрізнятися від HTTP-походження. Це зручно, коли ви хочете використовувати dev server Vite локально, але Gateway працює деінде.

```bash pnpm ui:dev ``` ```text http://localhost:5173/?gatewayUrl=ws://:18789 ```
Необов’язкова одноразова автентифікація (за потреби):

```text
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>
```
- `gatewayUrl` зберігається в localStorage після завантаження й видаляється з URL. - `token` слід передавати через фрагмент URL (`#token=...`), коли це можливо. Фрагменти не надсилаються на сервер, що запобігає витоку в журналах запитів і Referer. Застарілі параметри запиту `?token=` усе ще одноразово імпортуються для сумісності, але лише як запасний варіант, і видаляються одразу після bootstrap. - `password` зберігається лише в пам’яті. - Коли задано `gatewayUrl`, UI не повертається до облікових даних із конфігурації або середовища. Явно вкажіть `token` (або `password`). Відсутність явних облікових даних є помилкою. - Використовуйте `wss://`, коли Gateway розміщено за TLS (Tailscale Serve, HTTPS-проксі тощо). - `gatewayUrl` приймається лише у вікні верхнього рівня (не у вбудованому), щоб запобігти clickjacking. - Розгортання Control UI поза loopback повинні явно задавати `gateway.controlUi.allowedOrigins` (повні origins). Це також стосується віддалених dev-середовищ. - Під час запуску Gateway може ініціалізувати локальні origins, такі як `http://localhost:` і `http://127.0.0.1:`, з ефективної прив’язки та порту під час виконання, але для віддалених origins браузера все одно потрібні явні записи. - Не використовуйте `gateway.controlUi.allowedOrigins: ["*"]`, окрім як для жорстко контрольованого локального тестування. Це означає дозвіл для будь-якого browser origin, а не "збігатися з будь-яким хостом, який я використовую". - `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` вмикає режим резервного визначення origin через заголовок Host, але це небезпечний режим безпеки.

Приклад:

{
  gateway: {
    controlUi: {
      allowedOrigins: ["http://localhost:5173"],
    },
  },
}

Докладніше про налаштування віддаленого доступу: Віддалений доступ.

Пов’язане