Этот WebSocket сообщает открытому дашборду, что данные проекта могли измениться. Он не передаёт чат, состояние фоновой задачи или постоянный результат аудита. После project_updated клиент заново запрашивает нужный REST-ресурс.
Endpoint
wss://codegraph.example/api/v1/traceability/ws
Используйте ws только в доверенной локальной HTTP-среде. Страница, открытая по HTTPS, должна подключаться через wss.
Аутентификация
Не передавайте токен в URL. Query token отклоняется кодом 1008 и причиной “Query token transport is not allowed”.
Сервер принимает WebSocket и в течение 5 seconds ждёт первое сообщение клиента. Передайте объект с JWT:
{"token": "<JWT>"}
Runtime также принимает строку с токеном, но документированный контракт — JSON-объект. При ошибке аутентификации сервер отправляет событие error и закрывает соединение кодом 1008. Если первое сообщение не пришло за 5 seconds, соединение закрывается по тайм-ауту аутентификации.
Работа без токена разрешена только при явно включённом локальном режиме и loopback-адресах клиента и запрошенного хоста.
События
Сообщения дашборда используют поле event, а не envelope type/payload WebSocket приложения.
| event | Когда отправляется | Значимые поля |
|---|---|---|
| connected | Аутентификация и проверка квоты прошли | client_id, heartbeat_seconds |
| heartbeat | До истечения heartbeat-интервала клиент ничего не отправил | timestamp, clients |
| project_updated | Аудит, compliance, release или другой producer сообщил об изменении данных | project_name, trigger, timestamp |
| pong | Клиент отправил текст ping | нет |
| error | После accept не прошла аутентификация или квота сообщений | message |
project_updated сообщает об изменении данных producer. Авторитетный результат передаётся отдельным сообщением или запрашивается через соответствующий endpoint.
Пример для браузера
function connectDashboardSocket(accessToken) {
const scheme = location.protocol === "https:" ? "wss:" : "ws:";
const socket = new WebSocket(
scheme + "//" + location.host + "/api/v1/traceability/ws"
);
socket.addEventListener("open", () => {
socket.send(JSON.stringify({ token: accessToken }));
});
socket.addEventListener("message", async (event) => {
const message = JSON.parse(event.data);
if (message.event === "project_updated") {
await refreshDashboardResources(message.project_name);
}
});
return socket;
}
Не записывайте accessToken в лог и не добавляйте его в URL. Храните его не дольше, чем требуется аутентифицированной браузерной сессии.
Heartbeat и переподключение
После настроенного интервала без входящих сообщений сервер отправляет heartbeat. Клиент может передать обычный текст ping и получить событие pong.
Переподключайтесь с ограниченным exponential backoff и jitter. Если сессия истекла, до повторного подключения получите свежий токен. Не повторяйте соединение непрерывно после кода 1008: сначала устраните проблему аутентификации, конфигурации или rate limit.
После восстановления соединения перечитайте ресурсы дашборда через REST: события, возникшие во время разрыва, не воспроизводятся.
Конфигурация
dashboard:
websocket_enabled: true
websocket_heartbeat_seconds: 30
Эффективный heartbeat ограничен runtime-тайм-аутом WebSocket ping. Изменение конфигурации требует штатного процесса deployment/restart для установки.
Исходный контракт
- src/api/routers/dashboard_core/dashboard_ws.py — маршрут, аутентификация первым сообщением, события, heartbeat и квоты
- src/config/runtime_sections/unified_config_dashboard.py — настройки WebSocket дашборда
- src/api/app_routers.py — mount /api/v1/traceability
Для чата, прогресса задач и пользовательских уведомлений используйте WebSocket API приложения.