Перейти до основного вмісту

ADR-006: WebSocket-сповіщення

  • Статус: прийнято
  • Дата: 2026-04-16
  • Автор: CTO Agent (KALA-133)

Контекст

AgentCore уже мав WebSocket-інфраструктуру для прогресу agent-tasks. Новим потокам продукту знадобились live-сповіщення користувачам: схвалення, згадки, готові документи. Команда мала обрати: розширити існуючий WebSocket-плагін, додати server-sent events або обмежитись REST-опитуванням.

Рішення

Додаємо /ws/notifications до існуючого Fastify WebSocket-плагіна.

Канал сповіщень:

  1. автентифікується за тією ж JWT-моделлю, що й REST;
  2. підтримує query-token або first-message auth;
  3. підписується на notification-події для автентифікованого userId;
  4. відправляє notification.created-події, коли продюсери викликають emitNotification();
  5. тримає довготривалий стан у таблиці notifications.

Розглянуті альтернативи

Тільки REST-поллінг

Відхилено. Поллінг простий, але додає ack-latency до approval- та document-ready-воркфлоу і збільшує обсяг запитів для активних дашбордів.

Окремий SSE-ендпоінт

Поки відхилено. SSE підходить для server-to-server подій, але в застосунку вже є автентифікована WebSocket-система та тести. Додавати ще один транспорт — значить дублювати auth і lifecycle-логіку.

Розширити /ws/agent-tasks

Відхилено. Прогрес agent-task scope-обмежений по namespace/task. Сповіщення — це per-user inbox. Окремі шляхи не плутають subscription-семантику.

Наслідки

Позитивні

  • Перевикористовує існуючий WebSocket-плагін і JWT-шлях валідації.
  • Доставка сповіщень прибита до поточного користувача.
  • REST-inbox лишається source of truth після reconnect.
  • Тести можуть перевіряти сокет тими самими WebSocket-хелперами, які вже є.

Негативні

  • Поточний broadcast через EventEmitter локальний для процесу.
  • Багаторепліковий прод потребує Redis pub/sub або іншої shared event bus.
  • Клієнтам все одно треба REST-resync для подій, пропущених під час дисконекту.

Нотатки про реалізацію

  • src/lib/notifications.ts володіє emitNotification() і subscribeUserNotifications().
  • src/plugins/websocket.ts реєструє /ws/notifications.
  • Продюсери мають спочатку створити DB-рядок, а потім емітити подію.
  • Сокет закривається кодом 4001 при auth-таймауті або невалідному токені.