diff --git a/docs/uk/gateway/protocol.md b/docs/uk/gateway/protocol.md
index 7d77ee234..38694c572 100644
--- a/docs/uk/gateway/protocol.md
+++ b/docs/uk/gateway/protocol.md
@@ -1,29 +1,29 @@
---
read_when:
- - Реалізація або оновлення клієнтів Gateway WS
+ - Реалізація або оновлення WS-клієнтів Gateway
- Налагодження невідповідностей протоколу або збоїв підключення
- - Повторне генерування схеми/моделей протоколу
-summary: 'Протокол Gateway WebSocket: рукостискання, кадри, версіонування'
+ - Повторна генерація схем/моделей протоколу
+summary: 'Протокол WebSocket Gateway: рукостискання, кадри, версіонування'
title: Протокол Gateway
x-i18n:
- generated_at: "2026-04-10T06:30:21Z"
+ generated_at: "2026-04-16T00:43:06Z"
model: gpt-5.4
provider: openai
- source_hash: 83c820c46d4803d571c770468fd6782619eaa1dca253e156e8087dec735c127f
+ source_hash: 683e61ebe993a2d739bc34860060b0e3eda36b5c57267a2bcc03d177ec612fb3
source_path: gateway/protocol.md
workflow: 15
---
# Протокол Gateway (WebSocket)
-Протокол Gateway WS — це **єдина control plane + node transport** для
-OpenClaw. Усі клієнти (CLI, веб-UI, застосунок macOS, вузли iOS/Android, headless
-вузли) підключаються через WebSocket і оголошують свою **role** + **scope** під
-час рукостискання.
+Протокол WS Gateway — це **єдина контрольна площина + транспорт вузлів** для
+OpenClaw. Усі клієнти (CLI, вебінтерфейс, застосунок macOS, вузли iOS/Android,
+безголові вузли) підключаються через WebSocket і оголошують свою **роль** +
+**область дії** під час рукостискання.
## Транспорт
-- WebSocket, текстові кадри з JSON payload.
+- WebSocket, текстові кадри з корисним навантаженням JSON.
- Перший кадр **має** бути запитом `connect`.
## Рукостискання (connect)
@@ -80,10 +80,24 @@ Gateway → Client:
"type": "res",
"id": "…",
"ok": true,
- "payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
+ "payload": {
+ "type": "hello-ok",
+ "protocol": 3,
+ "server": { "version": "…", "connId": "…" },
+ "features": { "methods": ["…"], "events": ["…"] },
+ "snapshot": { "…": "…" },
+ "policy": {
+ "maxPayload": 26214400,
+ "maxBufferedBytes": 52428800,
+ "tickIntervalMs": 15000
+ }
+ }
}
```
+`server`, `features`, `snapshot` і `policy` є обов’язковими згідно зі схемою
+(`src/gateway/protocol/schema/frames.ts`). `auth` і `canvasHostUrl` є необов’язковими.
+
Коли видається токен пристрою, `hello-ok` також містить:
```json
@@ -96,8 +110,8 @@ Gateway → Client:
}
```
-Під час передавання довіреного bootstrap `hello-ok.auth` також може містити
-додаткові обмежені записи ролей у `deviceTokens`:
+Під час передавання в межах довіреного початкового завантаження `hello-ok.auth`
+також може містити додаткові обмежені записи ролей у `deviceTokens`:
```json
{
@@ -116,15 +130,15 @@ Gateway → Client:
}
```
-Для вбудованого потоку bootstrap node/operator основний токен вузла залишається
-`scopes: []`, а будь-який переданий токен оператора залишається обмеженим
-дозволеним списком bootstrap operator (`operator.approvals`, `operator.read`,
-`operator.talk.secrets`, `operator.write`). Перевірки scope bootstrap
-залишаються з префіксом role: записи operator задовольняють лише запити
-operator, а ролі, що не є operator, усе одно потребують scope під власним
-префіксом role.
+Для вбудованого потоку початкового завантаження вузла/оператора основний токен
+вузла зберігає `scopes: []`, а будь-який переданий токен оператора залишається
+обмеженим списком дозволів bootstrap-оператора (`operator.approvals`, `operator.read`,
+`operator.talk.secrets`, `operator.write`). Перевірки областей дії bootstrap
+залишаються прив’язаними до префікса ролі: записи оператора задовольняють лише
+запити оператора, а ролі, що не є оператором, усе одно потребують областей дії
+у межах префікса власної ролі.
-### Приклад node
+### Приклад вузла
```json
{
@@ -165,18 +179,18 @@ operator, а ролі, що не є operator, усе одно потребуют
- **Відповідь**: `{type:"res", id, ok, payload|error}`
- **Подія**: `{type:"event", event, payload, seq?, stateVersion?}`
-Методи з побічними ефектами потребують **idempotency keys** (див. схему).
+Методи з побічними ефектами вимагають **ключі ідемпотентності** (див. схему).
-## Roles + scopes
+## Ролі + області дії
-### Roles
+### Ролі
-- `operator` = клієнт control plane (CLI/UI/automation).
+- `operator` = клієнт контрольної площини (CLI/UI/автоматизація).
- `node` = хост можливостей (camera/screen/canvas/system.run).
-### Scopes (operator)
+### Області дії (operator)
-Поширені scope:
+Поширені області дії:
- `operator.read`
- `operator.write`
@@ -188,427 +202,475 @@ operator, а ролі, що не є operator, усе одно потребуют
Для `talk.config` з `includeSecrets: true` потрібен `operator.talk.secrets`
(або `operator.admin`).
-Зареєстровані plugin методи gateway RPC можуть вимагати власний scope operator,
-але зарезервовані префікси core admin (`config.*`, `exec.approvals.*`, `wizard.*`,
-`update.*`) завжди зводяться до `operator.admin`.
+RPC-методи Gateway, зареєстровані плагінами, можуть вимагати власну область дії
+оператора, але зарезервовані префікси основного адміністратора (`config.*`, `exec.approvals.*`, `wizard.*`,
+`update.*`) завжди зіставляються з `operator.admin`.
-Scope методу — лише перший бар’єр. Деякі slash-команди, до яких звертаються через
-`chat.send`, застосовують додаткові суворіші перевірки на рівні команди.
-Наприклад, постійні записи `/config set` і `/config unset` потребують `operator.admin`.
+Область дії методу — лише перший рівень перевірки. Для деяких slash-команд,
+доступних через `chat.send`, поверх цього застосовуються суворіші перевірки на
+рівні команди. Наприклад, постійні записи `/config set` і `/config unset`
+вимагають `operator.admin`.
-`node.pair.approve` також має додаткову перевірку scope під час схвалення понад
-базовий scope методу:
+`node.pair.approve` також має додаткову перевірку області дії під час
+затвердження поверх базової області дії методу:
-- запити без команди: `operator.pairing`
-- запити з командами вузла, що не є exec: `operator.pairing` + `operator.write`
-- запити, які містять `system.run`, `system.run.prepare` або `system.which`:
+- запити без команд: `operator.pairing`
+- запити з не-exec-командами вузла: `operator.pairing` + `operator.write`
+- запити, що включають `system.run`, `system.run.prepare` або `system.which`:
`operator.pairing` + `operator.admin`
### Caps/commands/permissions (node)
-Вузли оголошують claims можливостей під час підключення:
+Вузли оголошують заявлені можливості під час підключення:
- `caps`: високорівневі категорії можливостей.
-- `commands`: allowlist команд для invoke.
+- `commands`: список дозволених команд для invoke.
- `permissions`: детальні перемикачі (наприклад, `screen.record`, `camera.capture`).
-Gateway розглядає їх як **claims** і застосовує серверні allowlist.
+Gateway розглядає їх як **заяви** і застосовує списки дозволів на боці сервера.
## Presence
-- `system-presence` повертає записи, ключовані за ідентичністю пристрою.
+- `system-presence` повертає записи, ключовані ідентичністю пристрою.
- Записи presence містять `deviceId`, `roles` і `scopes`, щоб UI могли
- показувати один рядок на пристрій, навіть якщо він підключений і як **operator**,
+ показувати один рядок на пристрій, навіть якщо він підключається і як **operator**,
і як **node**.
## Поширені сімейства RPC-методів
-Ця сторінка не є згенерованим повним дампом, але публічна поверхня WS ширша,
-ніж наведені вище приклади рукостискання/автентифікації. Це основні сімейства
+Ця сторінка не є згенерованим повним дампом, але публічна WS-поверхня ширша,
+ніж наведені вище приклади рукостискання/автентифікації. Ось основні сімейства
методів, які Gateway надає сьогодні.
-`hello-ok.features.methods` — це консервативний список виявлення, зібраний із
-`src/gateway/server-methods-list.ts` плюс експорти методів завантажених plugin/channel.
-Сприймайте його як виявлення можливостей, а не як згенерований дамп кожного
-викличного helper, реалізованого в `src/gateway/server-methods/*.ts`.
+`hello-ok.features.methods` — це консервативний список виявлення, побудований з
+`src/gateway/server-methods-list.ts` плюс експортів методів завантажених плагінів/каналів.
+Сприймайте його як механізм виявлення можливостей, а не як згенерований дамп
+кожного викликаного допоміжного методу, реалізованого в `src/gateway/server-methods/*.ts`.
### Система та ідентичність
-- `health` повертає кешований або щойно перевірений знімок стану gateway.
-- `status` повертає зведення gateway у стилі `/status`; чутливі поля
- включаються лише для клієнтів operator з admin scope.
-- `gateway.identity.get` повертає ідентичність пристрою gateway, яка
- використовується в relay і потоках pairing.
+- `health` повертає кешований або щойно перевірений знімок стану Gateway.
+- `status` повертає зведення Gateway у стилі `/status`; чутливі поля
+ включаються лише для клієнтів operator з областю дії admin.
+- `gateway.identity.get` повертає ідентичність пристрою Gateway, яка
+ використовується потоками relay і pairing.
- `system-presence` повертає поточний знімок presence для підключених
пристроїв operator/node.
- `system-event` додає системну подію та може оновлювати/транслювати контекст
presence.
-- `last-heartbeat` повертає останню збережену подію heartbeat.
-- `set-heartbeats` перемикає обробку heartbeat у gateway.
+- `last-heartbeat` повертає останню збережену подію Heartbeat.
+- `set-heartbeats` перемикає обробку Heartbeat на Gateway.
### Моделі та використання
-- `models.list` повертає каталог моделей, дозволених під час виконання.
-- `usage.status` повертає вікна використання провайдерів/зведення залишкової квоти.
-- `usage.cost` повертає агреговані зведення використання вартості для діапазону дат.
-- `doctor.memory.status` повертає готовність vector-memory / embedding для
- активного робочого простору агента за замовчуванням.
-- `sessions.usage` повертає зведення використання за сеансами.
-- `sessions.usage.timeseries` повертає часовий ряд використання для одного сеансу.
-- `sessions.usage.logs` повертає записи журналу використання для одного сеансу.
+- `models.list` повертає каталог моделей, дозволених у середовищі виконання.
+- `usage.status` повертає зведення вікон використання постачальника/залишку квоти.
+- `usage.cost` повертає агреговані зведення вартості використання за діапазон дат.
+- `doctor.memory.status` повертає стан готовності векторної пам’яті / embeddings
+ для активного робочого простору агента за замовчуванням.
+- `sessions.usage` повертає зведення використання по сесіях.
+- `sessions.usage.timeseries` повертає часовий ряд використання для однієї сесії.
+- `sessions.usage.logs` повертає записи журналу використання для однієї сесії.
-### Канали та помічники входу
+### Канали та допоміжні засоби входу
-- `channels.status` повертає зведення стану вбудованих і bundled channel/plugin.
+- `channels.status` повертає зведення стану вбудованих і bundled каналів/плагінів.
- `channels.logout` виходить із конкретного каналу/облікового запису, якщо канал
підтримує вихід.
-- `web.login.start` запускає QR/web потік входу для поточного провайдера
- web-каналу з підтримкою QR.
-- `web.login.wait` очікує завершення цього QR/web потоку входу та запускає
- канал у разі успіху.
-- `push.test` надсилає тестовий push APNs до зареєстрованого вузла iOS.
-- `voicewake.get` повертає збережені тригери wake-word.
-- `voicewake.set` оновлює тригери wake-word і транслює зміну.
+- `web.login.start` запускає потік входу через QR/web для поточного QR-сумісного
+ постачальника вебканалу.
+- `web.login.wait` очікує завершення цього потоку входу через QR/web і в разі
+ успіху запускає канал.
+- `push.test` надсилає тестовий APNs push до зареєстрованого вузла iOS.
+- `voicewake.get` повертає збережені тригери слів пробудження.
+- `voicewake.set` оновлює тригери слів пробудження та транслює зміну.
### Повідомлення та журнали
-- `send` — це прямий RPC outbound-delivery для надсилання з націлюванням на
- channel/account/thread поза chat runner.
-- `logs.tail` повертає tail налаштованого файлового журналу gateway з контролем
- cursor/limit і max-byte.
+- `send` — це прямий RPC доставки назовні для надсилання в канал/обліковий
+ запис/тему поза межами виконувача чату.
+- `logs.tail` повертає хвіст налаштованого файлового журналу Gateway з
+ керуванням курсором/лімітом і максимальним розміром у байтах.
### Talk і TTS
-- `talk.config` повертає ефективний payload конфігурації Talk; `includeSecrets`
- потребує `operator.talk.secrets` (або `operator.admin`).
+- `talk.config` повертає корисне навантаження ефективної конфігурації Talk; для
+ `includeSecrets` потрібен `operator.talk.secrets` (або `operator.admin`).
- `talk.mode` встановлює/транслює поточний стан режиму Talk для клієнтів
WebChat/Control UI.
-- `talk.speak` синтезує мовлення через активного speech-провайдера Talk.
-- `tts.status` повертає стан увімкнення TTS, активного провайдера, резервних
- провайдерів і стан конфігурації провайдера.
-- `tts.providers` повертає видимий інвентар провайдерів TTS.
+- `talk.speak` синтезує мовлення через активного постачальника мовлення Talk.
+- `tts.status` повертає стан увімкнення TTS, активного постачальника,
+ резервних постачальників і стан конфігурації постачальника.
+- `tts.providers` повертає видимий інвентар постачальників TTS.
- `tts.enable` і `tts.disable` перемикають стан налаштувань TTS.
-- `tts.setProvider` оновлює бажаного провайдера TTS.
-- `tts.convert` виконує одноразове перетворення text-to-speech.
+- `tts.setProvider` оновлює бажаного постачальника TTS.
+- `tts.convert` виконує одноразове перетворення тексту на мовлення.
-### Секрети, конфігурація, оновлення та wizard
+### Секрети, конфігурація, оновлення та майстер
-- `secrets.reload` повторно розв’язує активні SecretRef і замінює стан секретів
- під час виконання лише за повного успіху.
-- `secrets.resolve` розв’язує призначення секретів цілі команди для конкретного
- набору command/target.
+- `secrets.reload` повторно зіставляє активні SecretRef і замінює стан секретів
+ у середовищі виконання лише за повного успіху.
+- `secrets.resolve` зіставляє призначення секретів для цільового набору
+ команд/цілей.
- `config.get` повертає поточний знімок конфігурації та хеш.
-- `config.set` записує валідований payload конфігурації.
+- `config.set` записує валідоване корисне навантаження конфігурації.
- `config.patch` об’єднує часткове оновлення конфігурації.
-- `config.apply` валідує і замінює повний payload конфігурації.
-- `config.schema` повертає payload живої схеми конфігурації, який використовують
- Control UI та інструменти CLI: schema, `uiHints`, версію та метадані
- генерування, включно з метаданими схеми plugin + channel, коли runtime може
+- `config.apply` виконує валідацію + повну заміну корисного навантаження конфігурації.
+- `config.schema` повертає корисне навантаження живої схеми конфігурації, яке
+ використовують Control UI і CLI: схема, `uiHints`, версія та метадані генерації,
+ включно з метаданими схем плагінів + каналів, коли середовище виконання може
їх завантажити. Схема містить метадані полів `title` / `description`,
- похідні від тих самих міток і довідкового тексту, які використовує UI,
- включно з вкладеним object, wildcard, array-item і гілками композиції
- `anyOf` / `oneOf` / `allOf`, коли існує відповідна документація поля.
-- `config.schema.lookup` повертає payload lookup з обмеженням шляхом для одного
- шляху конфігурації: нормалізований шлях, вузол поверхневої схеми, підібрану
- підказку + `hintPath` і зведення безпосередніх дочірніх елементів для
- поглибленого перегляду в UI/CLI.
- - Вузли схеми lookup зберігають документацію, орієнтовану на користувача, і
- поширені поля валідації: `title`, `description`, `type`, `enum`, `const`, `format`,
+ отримані з тих самих міток і довідкового тексту, що використовуються в UI,
+ включно з вкладеними об’єктами, wildcard, елементами масиву та гілками
+ композиції `anyOf` / `oneOf` / `allOf`, коли існує відповідна документація полів.
+- `config.schema.lookup` повертає корисне навантаження пошуку в межах шляху для
+ одного шляху конфігурації: нормалізований шлях, вузол неглибокої схеми,
+ відповідний hint + `hintPath` і зведення безпосередніх дочірніх елементів
+ для деталізації в UI/CLI.
+ - Вузли схеми lookup зберігають користувацьку документацію та поширені поля
+ валідації: `title`, `description`, `type`, `enum`, `const`, `format`,
`pattern`, числові/рядкові/масивні/об’єктні межі та булеві прапорці, як-от
`additionalProperties`, `deprecated`, `readOnly`, `writeOnly`.
- Зведення дочірніх елементів містять `key`, нормалізований `path`, `type`, `required`,
- `hasChildren`, а також підібрані `hint` / `hintPath`.
-- `update.run` запускає потік оновлення gateway і планує перезапуск лише тоді,
- коли саме оновлення виконалося успішно.
+ `hasChildren`, а також відповідні `hint` / `hintPath`.
+- `update.run` запускає потік оновлення Gateway і планує перезапуск лише тоді,
+ коли саме оновлення було успішним.
- `wizard.start`, `wizard.next`, `wizard.status` і `wizard.cancel` надають
- onboarding wizard через WS RPC.
+ майстер онбордингу через WS RPC.
### Наявні основні сімейства
-#### Помічники агента та робочого простору
+#### Допоміжні засоби агента та робочого простору
- `agents.list` повертає налаштовані записи агентів.
- `agents.create`, `agents.update` і `agents.delete` керують записами агентів і
прив’язкою робочого простору.
- `agents.files.list`, `agents.files.get` і `agents.files.set` керують файлами
- робочого простору bootstrap, доступними для агента.
-- `agent.identity.get` повертає ефективну ідентичність асистента для агента або сеансу.
-- `agent.wait` очікує завершення запуску та повертає термінальний знімок, коли
- він доступний.
+ bootstrap-робочого простору, доступними для агента.
+- `agent.identity.get` повертає ефективну ідентичність помічника для агента або
+ сесії.
+- `agent.wait` очікує завершення виконання та повертає фінальний знімок, якщо він доступний.
-#### Керування сеансом
+#### Керування сесією
-- `sessions.list` повертає поточний індекс сеансів.
-- `sessions.subscribe` і `sessions.unsubscribe` вмикають або вимикають підписки
- на події зміни сеансів для поточного WS-клієнта.
-- `sessions.messages.subscribe` і `sessions.messages.unsubscribe` вмикають або
- вимикають підписки на події transcript/message для одного сеансу.
-- `sessions.preview` повертає обмежені попередні перегляди transcript для
- конкретних ключів сеансу.
-- `sessions.resolve` розв’язує або канонікалізує ціль сеансу.
-- `sessions.create` створює новий запис сеансу.
-- `sessions.send` надсилає повідомлення в наявний сеанс.
-- `sessions.steer` — це варіант interrupt-and-steer для активного сеансу.
-- `sessions.abort` перериває активну роботу для сеансу.
-- `sessions.patch` оновлює метадані/перевизначення сеансу.
+- `sessions.list` повертає поточний індекс сесій.
+- `sessions.subscribe` і `sessions.unsubscribe` перемикають підписки на події
+ змін сесій для поточного WS-клієнта.
+- `sessions.messages.subscribe` і `sessions.messages.unsubscribe` перемикають
+ підписки на події транскрипту/повідомлень для однієї сесії.
+- `sessions.preview` повертає обмежені попередні перегляди транскриптів для
+ конкретних ключів сесій.
+- `sessions.resolve` зіставляє або канонізує ціль сесії.
+- `sessions.create` створює новий запис сесії.
+- `sessions.send` надсилає повідомлення до наявної сесії.
+- `sessions.steer` — це варіант переривання та спрямування для активної сесії.
+- `sessions.abort` перериває активну роботу для сесії.
+- `sessions.patch` оновлює метадані/перевизначення сесії.
- `sessions.reset`, `sessions.delete` і `sessions.compact` виконують
- обслуговування сеансу.
-- `sessions.get` повертає повний збережений рядок сеансу.
-- виконання chat, як і раніше, використовує `chat.history`, `chat.send`, `chat.abort` і
+ обслуговування сесії.
+- `sessions.get` повертає повний збережений рядок сесії.
+- виконання чату, як і раніше, використовує `chat.history`, `chat.send`, `chat.abort` і
`chat.inject`.
- `chat.history` нормалізується для відображення для UI-клієнтів: вбудовані теги
- directives видаляються з видимого тексту, XML payload plain-text tool-call
- (включно з `...`, `...`,
+ директив видаляються з видимого тексту, простотекстові XML-корисні
+ навантаження викликів інструментів (включно з
+ `...`, `...`,
`...`, `...` і
- обрізаними блоками tool-call) та витоки ASCII/full-width керувальних токенів
- моделі видаляються, чисті рядки assistant із silent-token, такі як точні
- `NO_REPLY` / `no_reply`, пропускаються, а надто великі рядки можуть
- замінюватися placeholder.
+ усіченими блоками викликів інструментів) та витеклі ASCII/повноширинні токени
+ керування моделлю видаляються, чисті рядки помічника з беззвучними токенами,
+ як-от точні `NO_REPLY` / `no_reply`, пропускаються, а надто великі рядки
+ можуть бути замінені заповнювачами.
#### Pairing пристроїв і токени пристроїв
-- `device.pair.list` повертає очікувальні та схвалені paired devices.
+- `device.pair.list` повертає очікувані й затверджені спарені пристрої.
- `device.pair.approve`, `device.pair.reject` і `device.pair.remove` керують
записами pairing пристроїв.
-- `device.token.rotate` ротує токен paired device в межах схвалених role і
- scope.
-- `device.token.revoke` відкликає токен paired device.
+- `device.token.rotate` ротує токен спареного пристрою в межах затверджених
+ обмежень ролі та області дії.
+- `device.token.revoke` відкликає токен спареного пристрою.
#### Pairing вузлів, invoke і відкладена робота
- `node.pair.request`, `node.pair.list`, `node.pair.approve`,
- `node.pair.reject` і `node.pair.verify` охоплюють pairing вузлів і
- bootstrap verification.
+ `node.pair.reject` і `node.pair.verify` охоплюють pairing вузлів і bootstrap
+ verification.
- `node.list` і `node.describe` повертають стан відомих/підключених вузлів.
-- `node.rename` оновлює мітку paired node.
+- `node.rename` оновлює мітку спареного вузла.
- `node.invoke` пересилає команду підключеному вузлу.
- `node.invoke.result` повертає результат для запиту invoke.
- `node.event` переносить події, що походять від вузла, назад у gateway.
-- `node.canvas.capability.refresh` оновлює токени canvas-capability з
- обмеженим scope.
+- `node.canvas.capability.refresh` оновлює токени можливостей canvas з
+ обмеженою областю дії.
- `node.pending.pull` і `node.pending.ack` — це API черги підключеного вузла.
- `node.pending.enqueue` і `node.pending.drain` керують стійкою відкладеною
- роботою для офлайн/відключених вузлів.
+ роботою для офлайн-/відключених вузлів.
-#### Сімейства approval
+#### Сімейства погоджень
- `exec.approval.request`, `exec.approval.get`, `exec.approval.list` і
- `exec.approval.resolve` охоплюють одноразові запити exec approval плюс
- lookup/replay відкладених approval.
-- `exec.approval.waitDecision` очікує на один відкладений exec approval і
+ `exec.approval.resolve` охоплюють одноразові запити погодження exec, а також
+ пошук/повторення відкладених погоджень.
+- `exec.approval.waitDecision` очікує на одне відкладене погодження exec і
повертає остаточне рішення (або `null` у разі тайм-ауту).
-- `exec.approvals.get` і `exec.approvals.set` керують знімками політики exec approval
- gateway.
+- `exec.approvals.get` і `exec.approvals.set` керують знімками політики
+ погоджень exec у gateway.
- `exec.approvals.node.get` і `exec.approvals.node.set` керують локальною
- політикою exec approval вузла через relay-команди вузла.
+ політикою погоджень exec вузла через relay-команди вузла.
- `plugin.approval.request`, `plugin.approval.list`,
- `plugin.approval.waitDecision` і `plugin.approval.resolve` охоплюють
- потоки approval, визначені plugin.
+ `plugin.approval.waitDecision` і `plugin.approval.resolve` охоплюють потоки
+ погодження, визначені плагінами.
#### Інші основні сімейства
- automation:
- - `wake` планує негайне або наступне введення тексту wake на heartbeat
+ - `wake` планує негайне або на наступний Heartbeat введення тексту пробудження
- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`,
`cron.run`, `cron.runs`
- skills/tools: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`
### Поширені сімейства подій
-- `chat`: оновлення UI chat, такі як `chat.inject` та інші події chat, що
- стосуються лише transcript.
-- `session.message` і `session.tool`: оновлення transcript/event-stream для
- сеансу, на який оформлено підписку.
-- `sessions.changed`: індекс сеансів або метадані змінилися.
+- `chat`: оновлення UI-чату, як-от `chat.inject` та інші події чату лише для
+ транскрипту.
+- `session.message` і `session.tool`: оновлення транскрипту/потоку подій для
+ сесії, на яку оформлено підписку.
+- `sessions.changed`: змінився індекс сесій або метадані.
- `presence`: оновлення знімка system presence.
- `tick`: періодична подія keepalive / liveness.
-- `health`: оновлення знімка стану gateway.
-- `heartbeat`: оновлення потоку подій heartbeat.
-- `cron`: подія зміни виконання/завдання cron.
-- `shutdown`: сповіщення про завершення роботи gateway.
+- `health`: оновлення знімка стану Gateway.
+- `heartbeat`: оновлення потоку подій Heartbeat.
+- `cron`: подія зміни запуску/завдання Cron.
+- `shutdown`: сповіщення про вимкнення Gateway.
- `node.pair.requested` / `node.pair.resolved`: життєвий цикл pairing вузла.
- `node.invoke.request`: трансляція запиту invoke вузла.
-- `device.pair.requested` / `device.pair.resolved`: життєвий цикл paired-device.
-- `voicewake.changed`: змінено конфігурацію тригера wake-word.
+- `device.pair.requested` / `device.pair.resolved`: життєвий цикл спареного пристрою.
+- `voicewake.changed`: змінено конфігурацію тригерів слів пробудження.
- `exec.approval.requested` / `exec.approval.resolved`: життєвий цикл
- exec approval.
+ погодження exec.
- `plugin.approval.requested` / `plugin.approval.resolved`: життєвий цикл
- plugin approval.
+ погодження плагіна.
-### Допоміжні методи node
+### Допоміжні методи вузла
-- Nodes можуть викликати `skills.bins`, щоб отримати поточний список виконуваних
- файлів skill для перевірок auto-allow.
+- Вузли можуть викликати `skills.bins`, щоб отримати поточний список
+ виконуваних файлів навичок для перевірок автодозволу.
-### Допоміжні методи operator
+### Допоміжні методи оператора
-- Operators можуть викликати `commands.list` (`operator.read`), щоб отримати
- інвентар команд під час виконання для агента.
- - `agentId` є необов’язковим; опустіть його, щоб читати робочий простір
+- Оператори можуть викликати `commands.list` (`operator.read`), щоб отримати
+ інвентар команд часу виконання для агента.
+ - `agentId` є необов’язковим; не вказуйте його, щоб читати робочий простір
агента за замовчуванням.
- - `scope` визначає, яку поверхню націлює основна `name`:
+ - `scope` керує тим, яку поверхню використовує основний `name`:
- `text` повертає основний текстовий токен команди без початкового `/`
- - `native` і шлях за замовчуванням `both` повертають native names,
- залежні від провайдера, коли вони доступні
- - `textAliases` містить точні slash-аліаси, такі як `/model` і `/m`.
- - `nativeName` містить native command name, залежне від провайдера, коли воно є.
- - `provider` є необов’язковим і впливає лише на native naming плюс
- доступність native plugin command.
- - `includeArgs=false` прибирає із відповіді серіалізовані метадані аргументів.
-- Operators можуть викликати `tools.catalog` (`operator.read`), щоб отримати каталог інструментів під час виконання для
- агента. Відповідь містить згруповані інструменти та метадані походження:
+ - `native` і типовий шлях `both` повертають нативні імена з урахуванням
+ постачальника, коли вони доступні
+ - `textAliases` містить точні slash-аліаси, як-от `/model` і `/m`.
+ - `nativeName` містить нативну назву команди з урахуванням постачальника,
+ коли така існує.
+ - `provider` є необов’язковим і впливає лише на нативне найменування та
+ доступність нативних команд плагіна.
+ - `includeArgs=false` не включає серіалізовані метадані аргументів із відповіді.
+- Оператори можуть викликати `tools.catalog` (`operator.read`), щоб отримати каталог інструментів
+ часу виконання для агента. Відповідь містить згруповані інструменти та метадані походження:
- `source`: `core` або `plugin`
- - `pluginId`: власник plugin, коли `source="plugin"`
- - `optional`: чи є plugin tool необов’язковим
-- Operators можуть викликати `tools.effective` (`operator.read`), щоб отримати інвентар інструментів, ефективний під час виконання,
- для сеансу.
+ - `pluginId`: власник плагіна, коли `source="plugin"`
+ - `optional`: чи є інструмент плагіна необов’язковим
+- Оператори можуть викликати `tools.effective` (`operator.read`), щоб отримати ефективний інвентар інструментів
+ часу виконання для сесії.
- `sessionKey` є обов’язковим.
- - Gateway виводить довірений runtime context із сеансу на стороні сервера,
- замість приймати auth або delivery context, наданий викликачем.
- - Відповідь має scope сеансу й відображає, що активна розмова може
- використовувати просто зараз, включно з core, plugin і channel tools.
-- Operators можуть викликати `skills.status` (`operator.read`), щоб отримати
- видимий інвентар skills для агента.
- - `agentId` є необов’язковим; опустіть його, щоб читати робочий простір
+ - Gateway виводить довірений контекст часу виконання з сесії на боці сервера
+ замість того, щоб приймати наданий викликачем контекст автентифікації або доставки.
+ - Відповідь прив’язана до сесії та відображає, що активна розмова може
+ використовувати прямо зараз, включно з інструментами core, plugin і channel.
+- Оператори можуть викликати `skills.status` (`operator.read`), щоб отримати
+ видимий інвентар Skills для агента.
+ - `agentId` є необов’язковим; не вказуйте його, щоб читати робочий простір
агента за замовчуванням.
- - Відповідь містить eligibility, відсутні вимоги, перевірки config і
- очищені параметри встановлення без розкриття необроблених значень secret.
-- Operators можуть викликати `skills.search` і `skills.detail` (`operator.read`) для
- метаданих виявлення ClawHub.
-- Operators можуть викликати `skills.install` (`operator.admin`) у двох режимах:
+ - Відповідь містить відповідність вимогам, відсутні вимоги, перевірки
+ конфігурації та санітизовані параметри встановлення без розкриття сирих
+ секретних значень.
+- Оператори можуть викликати `skills.search` і `skills.detail` (`operator.read`)
+ для метаданих виявлення ClawHub.
+- Оператори можуть викликати `skills.install` (`operator.admin`) у двох режимах:
- Режим ClawHub: `{ source: "clawhub", slug, version?, force? }` встановлює
- папку skill у каталог `skills/` робочого простору агента за замовчуванням.
- - Режим installer gateway: `{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
+ теку навички до каталогу `skills/` робочого простору агента за замовчуванням.
+ - Режим інсталятора Gateway: `{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
запускає оголошену дію `metadata.openclaw.install` на хості gateway.
-- Operators можуть викликати `skills.update` (`operator.admin`) у двох режимах:
- - Режим ClawHub оновлює один відстежуваний slug або всі відстежувані встановлення ClawHub у
- робочому просторі агента за замовчуванням.
- - Режим Config вносить зміни в значення `skills.entries.`, такі як `enabled`,
- `apiKey` і `env`.
+- Оператори можуть викликати `skills.update` (`operator.admin`) у двох режимах:
+ - Режим ClawHub оновлює один відстежуваний slug або всі відстежувані
+ встановлення ClawHub у робочому просторі агента за замовчуванням.
+ - Режим конфігурації вносить зміни до значень `skills.entries.`,
+ таких як `enabled`, `apiKey` і `env`.
-## Exec approval
+## Погодження exec
-- Коли запит exec потребує approval, gateway транслює `exec.approval.requested`.
-- Клієнти operator виконують підтвердження, викликаючи `exec.approval.resolve` (потрібен scope `operator.approvals`).
-- Для `host=node` `exec.approval.request` має містити `systemRunPlan` (канонічні метадані `argv`/`cwd`/`rawCommand`/сеансу). Запити без `systemRunPlan` відхиляються.
-- Після approval переслані виклики `node.invoke system.run` повторно
+- Коли запит exec потребує погодження, gateway транслює `exec.approval.requested`.
+- Клієнти operator виконують це через виклик `exec.approval.resolve` (потрібна область дії `operator.approvals`).
+- Для `host=node` `exec.approval.request` має містити `systemRunPlan` (канонічні `argv`/`cwd`/`rawCommand`/метадані сесії). Запити без `systemRunPlan` відхиляються.
+- Після погодження переслані виклики `node.invoke system.run` повторно
використовують цей канонічний `systemRunPlan` як авторитетний контекст
- command/cwd/session.
+ команди/cwd/сесії.
- Якщо викликач змінює `command`, `rawCommand`, `cwd`, `agentId` або
- `sessionKey` між prepare і остаточним пересиланням схваленого `system.run`,
- gateway відхиляє виконання, замість того щоб довіряти зміненому payload.
+ `sessionKey` між prepare і остаточним пересиланням погодженого `system.run`,
+ gateway відхиляє запуск замість того, щоб довіряти зміненому корисному
+ навантаженню.
## Резервна доставка агента
-- Запити `agent` можуть містити `deliver=true`, щоб запитати outbound delivery.
-- `bestEffortDeliver=false` зберігає сувору поведінку: нерозв’язані або лише внутрішні цілі delivery повертають `INVALID_REQUEST`.
-- `bestEffortDeliver=true` дозволяє резервний перехід до виконання лише в межах сеансу, коли неможливо розв’язати зовнішній маршрут доставки (наприклад, internal/webchat сеанси або неоднозначні multi-channel config).
+- Запити `agent` можуть включати `deliver=true`, щоб запросити вихідну доставку.
+- `bestEffortDeliver=false` зберігає сувору поведінку: нерозв’язані або лише внутрішні цілі доставки повертають `INVALID_REQUEST`.
+- `bestEffortDeliver=true` дозволяє резервний перехід до виконання лише в межах сесії, якщо неможливо визначити зовнішній маршрут доставки (наприклад, для внутрішніх/webchat-сесій або неоднозначних багатоканальних конфігурацій).
## Версіонування
-- `PROTOCOL_VERSION` знаходиться в `src/gateway/protocol/schema.ts`.
+- `PROTOCOL_VERSION` розташовано в `src/gateway/protocol/schema/protocol-schemas.ts`.
- Клієнти надсилають `minProtocol` + `maxProtocol`; сервер відхиляє невідповідності.
- Схеми + моделі генеруються з визначень TypeBox:
- `pnpm protocol:gen`
- `pnpm protocol:gen:swift`
- `pnpm protocol:check`
+### Константи клієнта
+
+Еталонний клієнт у `src/gateway/client.ts` використовує ці типові значення. Ці
+значення стабільні в межах протоколу v3 і є очікуваною базовою лінією для
+сторонніх клієнтів.
+
+| Константа | Типове значення | Джерело |
+| ----------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
+| `PROTOCOL_VERSION` | `3` | `src/gateway/protocol/schema/protocol-schemas.ts` |
+| Тайм-аут запиту (на RPC) | `30_000` ms | `src/gateway/client.ts` (`requestTimeoutMs`) |
+| Тайм-аут preauth / connect-challenge | `10_000` ms | `src/gateway/handshake-timeouts.ts` (обмеження `250`–`10_000`) |
+| Початковий backoff повторного підключення | `1_000` ms | `src/gateway/client.ts` (`backoffMs`) |
+| Максимальний backoff повторного підключення | `30_000` ms | `src/gateway/client.ts` (`scheduleReconnect`) |
+| Обмеження швидкого повтору після закриття токена пристрою | `250` ms | `src/gateway/client.ts` |
+| Пільговий період примусової зупинки перед `terminate()` | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
+| Типовий тайм-аут `stopAndWait()` | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` |
+| Типовий інтервал tick (до `hello-ok`) | `30_000` ms | `src/gateway/client.ts` |
+| Закриття через тайм-аут tick | код `4000`, коли тиша перевищує `tickIntervalMs * 2` | `src/gateway/client.ts` |
+| `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024` (25 MB) | `src/gateway/server-constants.ts` |
+
+Сервер оголошує ефективні `policy.tickIntervalMs`, `policy.maxPayload` і
+`policy.maxBufferedBytes` у `hello-ok`; клієнти повинні дотримуватися цих значень,
+а не типових значень до рукостискання.
+
## Автентифікація
-- Автентифікація gateway зі спільним секретом використовує `connect.params.auth.token` або
- `connect.params.auth.password`, залежно від налаштованого режиму auth.
-- Режими з передаванням ідентичності, такі як Tailscale Serve
- (`gateway.auth.allowTailscale: true`) або не-loopback
- `gateway.auth.mode: "trusted-proxy"`, задовольняють перевірку auth під час connect за
- заголовками запиту, а не через `connect.params.auth.*`.
-- Private-ingress `gateway.auth.mode: "none"` повністю пропускає автентифікацію connect зі спільним секретом; не відкривайте цей режим для публічного/недовіреного ingress.
-- Після pairing Gateway видає **токен пристрою** з обмеженням на role + scopes
- підключення. Він повертається в `hello-ok.auth.deviceToken` і має бути
- збережений клієнтом для майбутніх підключень.
-- Клієнти повинні зберігати основний `hello-ok.auth.deviceToken` після будь-якого
+- Автентифікація Gateway через спільний секрет використовує `connect.params.auth.token` або
+ `connect.params.auth.password` залежно від налаштованого режиму автентифікації.
+- Режими з ідентичністю, як-от Tailscale Serve
+ (`gateway.auth.allowTailscale: true`) або non-loopback
+ `gateway.auth.mode: "trusted-proxy"`, проходять перевірку автентифікації connect за
+ заголовками запиту замість `connect.params.auth.*`.
+- `gateway.auth.mode: "none"` для приватного ingress повністю пропускає
+ автентифікацію connect через спільний секрет; не відкривайте цей режим для
+ публічного/ненадійного ingress.
+- Після pairing Gateway видає **токен пристрою**, обмежений роллю + областями
+ дії підключення. Він повертається в `hello-ok.auth.deviceToken` і має
+ зберігатися клієнтом для майбутніх підключень.
+- Клієнти повинні зберігати основний `hello-ok.auth.deviceToken` після кожного
успішного підключення.
- Повторне підключення з цим **збереженим** токеном пристрою також має
- повторно використовувати збережений набір схвалених scope для цього токена.
- Це зберігає вже наданий доступ на читання/перевірку/status і запобігає
- тихому звуженню повторних підключень до вужчого неявного scope лише admin.
-- Звичайний пріоритет auth під час connect: спочатку явний спільний token/password, потім
- явний `deviceToken`, потім збережений токен для пристрою, потім bootstrap token.
+ повторно використовувати збережений затверджений набір областей дії для цього
+ токена. Це зберігає вже наданий доступ для читання/перевірок/статусу й
+ запобігає непомітному звуженню повторних підключень до вужчої неявної
+ області дії лише admin.
+- Формування автентифікації connect на боці клієнта (`selectConnectAuth` у
+ `src/gateway/client.ts`):
+ - `auth.password` є ортогональним і завжди пересилається, якщо заданий.
+ - `auth.token` заповнюється в такому порядку пріоритету: спочатку явний
+ спільний токен, потім явний `deviceToken`, потім збережений токен
+ пристрою для конкретного пристрою (ключ: `deviceId` + `role`).
+ - `auth.bootstrapToken` надсилається лише тоді, коли жоден із наведених вище
+ варіантів не дав значення для `auth.token`. Спільний токен або будь-який
+ визначений токен пристрою його пригнічує.
+ - Автопідвищення збереженого токена пристрою під час одноразової повторної
+ спроби `AUTH_TOKEN_MISMATCH` обмежене **лише довіреними endpoint** —
+ loopback або `wss://` із закріпленим `tlsFingerprint`. Публічний `wss://`
+ без pinning не підходить.
- Додаткові записи `hello-ok.auth.deviceTokens` — це токени передавання bootstrap.
- Зберігайте їх лише тоді, коли connect використовував bootstrap auth через
- довірений транспорт, такий як `wss://` або loopback/local pairing.
-- Якщо клієнт надає **явний** `deviceToken` або явні `scopes`, цей набір scope,
- запитаний викликачем, залишається авторитетним; кешовані scope повторно
- використовуються лише тоді, коли клієнт повторно використовує збережений токен для пристрою.
-- Токени пристрою можна ротувати/відкликати через `device.token.rotate` і
- `device.token.revoke` (потрібен scope `operator.pairing`).
-- Видача/ротація токенів залишається обмеженою схваленим набором role,
- зафіксованим у записі pairing цього пристрою; ротація токена не може
- розширити пристрій до role, яку pairing approval ніколи не надавав.
-- Для сесій токенів paired-device керування пристроєм має власне scope, якщо
- викликач також не має `operator.admin`: викликачі без admin можуть
- видаляти/відкликати/ротувати лише **власний** запис пристрою.
-- `device.token.rotate` також перевіряє запитаний набір scope operator щодо
- поточних scope сесії викликача. Викликачі без admin не можуть ротувати
- токен до ширшого набору scope operator, ніж уже мають.
-- Збої auth містять `error.details.code` плюс підказки для відновлення:
+ Зберігайте їх лише тоді, коли підключення використовувало bootstrap auth через
+ довірений транспорт, наприклад `wss://` або loopback/local pairing.
+- Якщо клієнт надає **явний** `deviceToken` або явні `scopes`, цей
+ запитаний викликачем набір областей дії залишається авторитетним; кешовані
+ області дії повторно використовуються лише тоді, коли клієнт повторно
+ використовує збережений токен пристрою для конкретного пристрою.
+- Токени пристроїв можна ротувати/відкликати через `device.token.rotate` і
+ `device.token.revoke` (потрібна область дії `operator.pairing`).
+- Видача/ротація токенів залишається обмеженою затвердженим набором ролей,
+ записаним у записі pairing цього пристрою; ротація токена не може розширити
+ пристрій до ролі, яку pairing approval ніколи не надавав.
+- Для сесій токенів спарених пристроїв керування пристроями є самостійно
+ обмеженим, якщо тільки викликач також не має `operator.admin`: викликачі без
+ прав admin можуть видаляти/відкликати/ротувати лише **власний** запис пристрою.
+- `device.token.rotate` також перевіряє запитаний набір областей дії оператора
+ щодо поточних областей дії сесії викликача. Викликачі без прав admin не
+ можуть ротувати токен до ширшого набору областей дії оператора, ніж вони вже мають.
+- Збої автентифікації містять `error.details.code` плюс підказки для
+ відновлення:
- `error.details.canRetryWithDeviceToken` (boolean)
- `error.details.recommendedNextStep` (`retry_with_device_token`, `update_auth_configuration`, `update_auth_credentials`, `wait_then_retry`, `review_auth_configuration`)
- Поведінка клієнта для `AUTH_TOKEN_MISMATCH`:
- - Довірені клієнти можуть виконати одну обмежену повторну спробу з кешованим токеном для пристрою.
- - Якщо ця повторна спроба не вдається, клієнти повинні зупинити автоматичні цикли перепідключення та показати вказівки для дій оператора.
+ - Довірені клієнти можуть виконати одну обмежену повторну спробу з кешованим
+ токеном пристрою для конкретного пристрою.
+ - Якщо ця повторна спроба не вдається, клієнти повинні припинити автоматичні
+ цикли повторного підключення й показати оператору вказівки щодо подальших дій.
## Ідентичність пристрою + pairing
-- Nodes повинні включати стабільну ідентичність пристрою (`device.id`), похідну
- від відбитка keypair.
-- Gateways видають токени для кожного пристрою + role.
-- Для нових device ID потрібні pairing approval, якщо не ввімкнено локальне auto-approval.
-- Pairing auto-approval зосереджене на прямих локальних підключеннях local loopback.
-- OpenClaw також має вузький backend/container-local шлях self-connect для
- довірених helper-потоків зі спільним секретом.
-- Підключення tailnet або LAN з того самого хоста все одно вважаються віддаленими для pairing і
- потребують approval.
+- Вузли повинні включати стабільну ідентичність пристрою (`device.id`),
+ похідну від відбитка keypair.
+- Gateway видає токени для кожного пристрою + ролі.
+- Для нових `device.id` потрібні pairing approvals, якщо не ввімкнено локальне
+ auto-approval.
+- Pairing auto-approval зосереджене на прямих локальних loopback-підключеннях.
+- OpenClaw також має вузький шлях self-connect для backend/container-local
+ довірених потоків helper зі спільним секретом.
+- Підключення tailnet або LAN на тому самому хості однаково вважаються
+ віддаленими для pairing і потребують approval.
- Усі WS-клієнти мають включати ідентичність `device` під час `connect` (operator + node).
- Control UI може опускати її лише в таких режимах:
+ Control UI може пропустити її лише в таких режимах:
- `gateway.controlUi.allowInsecureAuth=true` для сумісності з небезпечним HTTP лише на localhost.
- - успішна автентифікація operator Control UI з `gateway.auth.mode: "trusted-proxy"`.
+ - успішна автентифікація operator Control UI через `gateway.auth.mode: "trusted-proxy"`.
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (аварійний режим, серйозне зниження безпеки).
- Усі підключення мають підписувати наданий сервером nonce `connect.challenge`.
### Діагностика міграції автентифікації пристрою
Для застарілих клієнтів, які все ще використовують поведінку підписування до challenge, `connect` тепер повертає
-коди деталей `DEVICE_AUTH_*` у `error.details.code` зі стабільним `error.details.reason`.
+коди деталей `DEVICE_AUTH_*` у `error.details.code` разом зі стабільним `error.details.reason`.
Поширені збої міграції:
-| Повідомлення | details.code | details.reason | Значення |
-| -------------------------------- | -------------------------------- | ------------------------ | -------------------------------------------------- |
-| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Клієнт пропустив `device.nonce` (або надіслав порожнє значення). |
-| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Клієнт підписав застарілим/неправильним nonce. |
-| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Payload підпису не відповідає payload v2. |
-| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Підписана мітка часу виходить за межі дозволеного зсуву. |
-| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` не збігається з відбитком відкритого ключа. |
-| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Не вдалося виконати форматування/канонікалізацію відкритого ключа. |
+| Повідомлення | details.code | details.reason | Значення |
+| --------------------------- | -------------------------------- | ------------------------ | -------------------------------------------------- |
+| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Клієнт не вказав `device.nonce` (або надіслав порожнє значення). |
+| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Клієнт підписався застарілим/неправильним nonce. |
+| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Корисне навантаження підпису не відповідає корисному навантаженню v2. |
+| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Підписана часова позначка виходить за межі дозволеного відхилення. |
+| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` не відповідає відбитку публічного ключа. |
+| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Не вдалося виконати форматування/канонізацію публічного ключа. |
Ціль міграції:
-- Завжди очікуйте `connect.challenge`.
-- Підписуйте payload v2, який містить nonce сервера.
+- Завжди чекайте на `connect.challenge`.
+- Підписуйте корисне навантаження v2, яке містить server nonce.
- Надсилайте той самий nonce у `connect.params.device.nonce`.
-- Бажаний payload підпису — `v3`, який прив’язує `platform` і `deviceFamily`
+- Бажаним корисним навантаженням підпису є `v3`, яке прив’язує `platform` і `deviceFamily`
на додачу до полів device/client/role/scopes/token/nonce.
- Застарілі підписи `v2` і далі приймаються для сумісності, але pinning
- метаданих paired-device усе одно керує політикою команд під час повторного підключення.
+ метаданих спарених пристроїв усе одно керує політикою команд під час повторного підключення.
## TLS + pinning
-- Для WS-підключень підтримується TLS.
-- Клієнти за бажанням можуть закріплювати відбиток сертифіката gateway (див. конфігурацію `gateway.tls`
+- TLS підтримується для WS-підключень.
+- Клієнти за бажання можуть закріпити відбиток сертифіката gateway (див. конфігурацію `gateway.tls`
плюс `gateway.remote.tlsFingerprint` або CLI `--tls-fingerprint`).
-## Scope
+## Область застосування
-Цей протокол відкриває **повний API gateway** (status, channels, models, chat,
-agent, sessions, nodes, approvals тощо). Точна поверхня визначається
+Цей протокол надає **повний API gateway** (status, channels, models, chat,
+agent, sessions, nodes, approvals тощо). Точна поверхня визначена
схемами TypeBox у `src/gateway/protocol/schema.ts`.