Gateway

Протокол мосту

Навіщо він існував

  • Межа безпеки: міст надає невеликий allowlist замість повної поверхні API gateway.
  • Сполучення + ідентичність вузла: допуск вузлів належить gateway і прив’язаний до токена для кожного вузла.
  • UX виявлення: вузли можуть виявляти gateway через Bonjour у LAN або підключатися напряму через tailnet.
  • Loopback WS: повна площина керування WS залишається локальною, якщо її не тунельовано через SSH.

Транспорт

  • TCP, один об’єкт JSON на рядок (JSONL).
  • Необов’язковий TLS (коли bridge.tls.enabled має значення true).
  • Історичний типовий порт слухача був 18790 (поточні збірки не запускають міст TCP).

Коли TLS увімкнено, TXT-записи виявлення містять bridgeTls=1 плюс bridgeTlsSha256 як несекретну підказку. Зауважте, що TXT-записи Bonjour/mDNS не автентифіковані; клієнти не повинні вважати оголошений відбиток авторитетним закріпленням без явного наміру користувача або іншої позасмугової перевірки.

Handshake + сполучення

  1. Клієнт надсилає hello з метаданими вузла + токеном (якщо вже сполучений).
  2. Якщо не сполучений, gateway відповідає error (NOT_PAIRED/UNAUTHORIZED).
  3. Клієнт надсилає pair-request.
  4. Gateway чекає на схвалення, потім надсилає pair-ok і hello-ok.

Історично hello-ok повертав serverName; розміщені поверхні Plugin тепер оголошуються через pluginSurfaceUrls. Canvas/A2UI використовує pluginSurfaceUrls.canvas; застарілий псевдонім canvasHostUrl не є частиною переробленого протоколу.

Фрейми

Клієнт → Gateway:

  • req / res: scoped gateway RPC (chat, sessions, config, health, voicewake, skills.bins)
  • event: сигнали вузла (голосова транскрипція, запит агента, підписка на чат, життєвий цикл exec)

Gateway → Клієнт:

  • invoke / invoke-res: команди вузла (canvas.*, camera.*, screen.record, location.get, sms.send)
  • event: оновлення чату для підписаних сесій
  • ping / pong: keepalive

Застаріле застосування allowlist розташовувалося в src/gateway/server-bridge.ts (видалено).

Події життєвого циклу exec

Вузли можуть emit події exec.finished або exec.denied, щоб показати активність system.run. Вони зіставляються із системними подіями в gateway. (Застарілі вузли можуть усе ще emit exec.started.)

Поля payload (усі необов’язкові, якщо не зазначено інше):

  • sessionKey (обов’язково): сесія агента, яка має отримати системну подію.
  • runId: унікальний id exec для групування.
  • command: raw або відформатований рядок команди.
  • exitCode, timedOut, success, output: деталі завершення (лише finished).
  • reason: причина відмови (лише denied).

Історичне використання tailnet

  • Прив’яжіть міст до IP tailnet: bridge.bind: "tailnet" у ~/.openclaw/openclaw.json (лише історично; bridge.* більше не є дійсним).
  • Клієнти підключаються через ім’я MagicDNS або IP tailnet.
  • Bonjour не перетинає мережі; за потреби використовуйте ручні host/port або wide-area DNS-SD.

Версійність

Міст був неявним v1 (без узгодження min/max). Цей розділ є лише історичною довідкою; поточні клієнти вузлів/операторів використовують WebSocket протокол Gateway.

Пов’язане