🖥️ WebSocket-консоль приложений (демон)
📌 Описание
Демон предоставляет WebSocket-консоль конкретного приложения: терминал и live-стрим логов в браузере (attach к контейнеру или журналу нативного приложения).
🎯 Сценарии использования
- 🧑💻 Разработчик открывает вкладку «Консоль» приложения — видит live-вывод и вводит команды в stdin (например, консоль Minecraft-сервера).
- 🔎 Во вкладке «Логи» ищет момент падения по временным меткам и фильтру.
🏗️ Техническое решение
🖥️ Вкладки приложения в UI
У каждого приложения в платформе — две вкладки:
- Консоль — реальное время: стрим вывода Docker-приложения или runtime-процесса нативного приложения; снизу — строка ввода команд в stdin приложения. Это интерактивная сессия (attach), а не просто просмотр.
- Логи — история: каждая строка с временной меткой, поиск/фильтрация по тексту, сортировка по времени, выбор диапазона; переход «показать в контексте» из результата поиска.
🎨 Терминал
Терминал — удобный и современный: xterm.js, полная поддержка ANSI-цветов и управляющих последовательностей, автоподбор размера (resize → PTY), копирование/вставка, поиск по буферу, история прокрутки, выбор шрифта/темы (наследует тему UI).
⚙️ Транспорт
- WebSocket-консоль: сервер в демоне; сессии
logs(read-only стрим: docker logs -f / journald follow, с метками времени) иattach(PTY/stdin приложения, двунаправленно). Протокол — бинарные фреймы (stdin/stdout/resize) как в ttyd/gotty. - Доступ по временному токену: WebSocket-подключение к консоли открывается только с временным токеном, который выдаётся через API демона (
AppService.IssueConsoleToken/POST /v1/apps/{id}/console-token): TTL 30 секунд, одноразовый, привязан к приложению и типу сессииlogs/attach. Платформа получает токен автоматически при открытии вкладки консоли (backend проверяет права → запрашивает токен у демона → передаёт его браузеру); в автономном режиме токен выдаёт CLI (asc app console-token <id>). - Endpoint:
GET /v1/console?token=<токен>[&tail=N]— вне bearer-аутентификации API (браузер не может выставить заголовки на WS-handshake), защита — только одноразовым токеном; неверный/использованный токен → 401 до апгрейда. - Реализация MVP (DMN-007): сессия
logs— текстовые фреймы, источник по рантайму: для Docker — стрим логов через Engine API (follow+ timestamps по unix-сокету); для systemd —journalctl -f -o short-iso; для process —tail -F app.log(subprocess убивается при отключении клиента). Сессияattach— пока только Docker (Engine APIattach, бинарные фреймы stdin/stdout); для systemd/process нужен PTY при запуске — придёт вместе с бинарным протоколом ttyd-стиля (resize и пр.) при работе над UI (FE-006). - Несколько подключений к одному приложению (вкладки/пользователи):
attach-сессии мультиклиентные по схеме wings — в демоне на приложение создаётся одна общая сессия-источник (hub), её вывод раздаётся всем подключениям через broadcast-канал; отстающий клиент теряет старые чанки, но не тормозит остальных. Hub держит replay-буфер последних ~128 КиБ вывода — новая вкладка сразу видит недавний вывод, а stdin всех клиентов сходится в один пайп контейнера. Источник (Engine APIattach) закрывается вместе с последним клиентом.logs-сессии независимы по построению: каждое подключение — свой follow-поток со своимtail, поэтому несколько вкладок работают и там. - CLI:
asc attach <id>(синонимasc app attach <id>) — интерактивная консоль приложения прямо из терминала сервера: stdin/stdout процесса CLI пробрасываются в приложение. При запущенном демоне CLI идёт через собственную консоль демона (DMN-043): запрашивает токен консоли по unix-сокету и открывает ту же WebSocket-сессию, что и браузер, поэтому обычному пользователю не нужны ни членство в группеdocker, ни доступ к root-owned дереву приложений — авторизацию полностью определяет peer uid, прочитанный демоном из сокета. Без демона (автономная установка) CLI идёт напрямую в Engine API. В обоих случаях Docker раздаёт вывод всем подключённым (CLI + вкладки браузера). Пока только Docker-приложения; systemd/process — вместе с PTY (FE-006). Отключение — Ctrl+C, приложение продолжает работать. - Маршрутизация: браузер ↔ nodeservice (wss) ↔ туннель демона ↔ модуль консоли.
- Права: доступ к консоли приложения регулируется правом
apps.console(🔐 access-control).
🔗 Связанные задачи
DMN-007 и FE-006 в ROADMAP.md.