19 KiB
LPRA 0.2.0 — рабочее пространство (подпроект 1)
Дата: 2026-10-15. Статус: спецификация утверждена. Подпроект 2 (встроенный ИИ-помощник) — отдельная спецификация, делается после этого.
Цель
Работа с несколькими машинами в одном месте, без потери открытых терминалов при переходах по панели. Терминалы, файловые менеджеры (своих машин и по SSH) живут во вкладках одного рабочего пространства; файлы перетаскиваются между панелями и в терминал.
Критерии готовности:
- переход Машины ↔ Терминал ↔ Настройки не обрывает сессии терминалов и не сбрасывает вкладки;
- перезагрузка страницы сбрасывает пространство (с предупреждением браузера, если есть живые сессии);
- файловый менеджер — тип панели во вкладке, в том числе по SSH;
- перетаскивание файлов: между файловыми панелями (окно «переместить / копировать»), в терминал той же машины (вставка путей), в терминал другой машины — запрет с сообщением.
Решения, принятые в обсуждении
| вопрос | решение |
|---|---|
| Страницы «Порты», «Статус», «Изменить» | окна поверх текущей страницы |
| Файлы рядом с терминалами в одной вкладке | да: любая из до 4 панелей — терминал, SSH-терминал, файлы, SSH-файлы |
| Перезагрузка при живых сессиях | вопрос браузера «Покинуть сайт?» |
| Архитектура | одностраничная оболочка, остальное — HTML-фрагменты с сервера (вариант A) |
| Файлы по SSH | без SFTP-библиотеки: команды на хосте через SSH, как у существующей передачи tar |
| Состояние | одно на вкладку браузера, в памяти страницы; не сохраняется при перезагрузке |
1. Каркас и маршруты
Оболочка. Адреса /, /terminal, /settings отдают один шаблон app.html: шапка (LPRA, «Машины · Терминал · Настройки» — «Настройки» только администраторам, статус активной панели, аккаунт) и три области <section data-view="machines|terminal|settings">.
Старые адреса /agents/{id}/terminal и /agents/{id}/files отдают ту же оболочку и при загрузке создают вкладку нужного типа для этой машины (закладки не ломаются).
Роутер (static/app.js, без библиотек):
- перехватывает клики по внутренним ссылкам и
popstate; меняет видимую область черезhistory.pushState, подсвечивает пункт шапки; - область «Терминал» создаётся один раз и потом только скрывается (
hidden) — сессии, WebSocket и xterm живут, пока жива вкладка браузера; - «Машины» и «Настройки» при каждом показе подгружаются заново как фрагмент:
GET /?frag=1,GET /settings?frag=1.
Фрагменты на сервере. render() получает режим фрагмента (параметр frag=1): шаблон отдаёт только содержимое, без <html>, шапки и подключений. Общая разметка head и topbar, сейчас скопированная в каждый шаблон, выносится в {{define}}-блоки.
Формы во фрагментах (app.js, перехват submit внутри областей и окон):
onsubmit-обработчики (confirm(...)) срабатывают как обычно; отказ — ничего не происходит;- форма отправляется через
fetch(redirect: 'follow', тело —FormData); - итоговый адрес ответа определяет, что перерисовать: тот же фрагмент по этому адресу (сохраняются
?err=...,?updated=1,#users); - формы на
/logoutи ссылки наружу работают обычной загрузкой страницы.
Скрипты фрагментов. Встроенные <script> во фрагментах не исполняются. Поведение страниц оформляется модулями с mount(root) / unmount(), которые вызывает роутер: копирование команд и коды установки (настройки), users.js, список машин с опросом присутствия.
pin.js, scroll.js, account.js подключаются один раз в оболочке.
Предупреждение при уходе. beforeunload спрашивает «Покинуть сайт?», только если в рабочем пространстве есть живая сессия терминала или SSH-терминала.
2. Рабочее пространство и типы панелей
Модель. Вкладка содержит 1–4 панели в существующих раскладках (1, h, v, сетка), с изменением размеров и перетаскиванием панелей и вкладок, как сейчас. Тип панели:
| тип | что это |
|---|---|
term |
терминал на машине (как сейчас) |
ssh |
SSH-терминал через машину (как сейчас) |
files |
файловый менеджер на машине |
sshfiles |
файловый менеджер на SSH-хосте через машину |
Разделение кода (сейчас всё в terminal.js и files.html):
workspace.js— вкладки, раскладки, разделение, перетаскивание панелей и вкладок, меню «+». С панелями работает через общий интерфейс:el,kind,agent,title,stateиtext(точка и строка статуса),fit(),focus(),close(),acceptsDrop(item),drop(item);termpane.js— нынешний классSession(терминал и SSH-терминал), вынесенный почти без изменений;filepane.js— файловая панель (часть 3);fileviews.js— общие окна файлов (просмотр и правка, hex, свойства, перемещение, загрузка, редактор SQLite).
Меню «+» (на компьютере и телефоне):
- «Терминал ›» — «здесь (машина)», другие машины в сети, «SSH-хост…»;
- «Файловый менеджер ›» — «здесь (машина)», другие машины в сети, «SSH-хост…».
«SSH-хост…» открывает существующее окно SSH-подключения; тип панели зависит от пункта меню. Последний SSH-хост (без секретов) запоминается, как сейчас.
Из списка машин: кнопка терминала → новая вкладка-терминал этой машины и переход в «Терминал»; кнопка файлов → новая вкладка «Файлы». Если пространства ещё нет, оно создаётся.
Заголовки. Вкладка файлов — иконка папки и машина · папка, путь обрезается слева, обновляется при смене папки. Переименование двойным кликом — как у терминалов. Точка статуса файловой панели — машина в сети / офлайн / ошибка.
Телефон. Вкладки и меню те же; разделения и перетаскивания, как и сейчас, только на компьютере.
3. Файловая панель
Содержимое нынешней страницы файлов как компонент FilePane(source): строка пути, «Вверх», «Обновить», «Папка / Файл / Загрузить», таблица с отметками, «В zip», «Удалить выбранное», загрузка перетаскиванием из ОС.
Состояние (текущая папка, список, отметки) — у экземпляра; элементы ищутся внутри корня панели, без глобальных id. Две файловые панели в одной вкладке не мешают друг другу.
Общие окна (fileviews.js) — одно на страницу. При открытии окну передаётся панель-источник: машина или SSH, путь, что обновить после действия.
Источник данных — один интерфейс (list, read, write, mkdir, delete, move, copy, stat, chmod, download, upload) с двумя реализациями:
- машина — существующий
/api/panel/agents/{id}/fs/...; - SSH-хост — новые задачи агента
sshfs.*(ниже).
Узкие панели (меньше ~520 px, в разделённой вкладке): прячется колонка «Изменён», кнопки строки сворачиваются в меню «⋯» — как сейчас на телефоне.
Файлы по SSH (sshfiles)
Агент держит одно SSH-подключение на панель: sshConnect и проверка ключа хоста из SSH-терминала. Подключение открывается при создании панели (окно «SSH-хост…»), получает id, закрывается при закрытии панели или через 10 минут простоя. Секреты передаются агенту один раз, панель их не хранит.
Операции — команды на хосте, пути в одинарных кавычках (shq):
| операция | команда |
|---|---|
| список | stat по содержимому папки; формат выбирается один раз при подключении: GNU/busybox stat -c, BSD/macOS stat -f; без stat — разбор ls -la без точного времени |
| чтение, скачивание | cat -- 'файл', поток через stdout |
| запись, загрузка | cat > 'файл.tmp' && mv 'файл.tmp' 'файл', поток через stdin |
| папка, удаление, переименование | mkdir -p, rm -rf, mv |
| права, владелец | chmod, chown |
| копирование, перенос внутри хоста | cp -a, mv |
| перенос между хостом и машинами | существующая передача tar по SSH |
Новые задачи агента: sshfs.open (подключиться, вернуть id и домашнюю папку), sshfs.close, sshfs.list, sshfs.read, sshfs.write, sshfs.mkdir, sshfs.delete, sshfs.move, sshfs.copy, sshfs.stat, sshfs.chmod, sshfs.send (скачивание через существующие куски xfer), sshfs.put (загрузка через куски xfer).
Серверу — те же правила доступа, что у файловых операций машины; изменения пишутся в аудит.
Не входит: zip и распаковка на SSH-хосте, редактор SQLite по SSH — эти кнопки в sshfiles скрыты. Новых зависимостей нет.
4. Перетаскивание
Что тащится: строка файла или папки; если строка отмечена — все отмеченные строки панели. У курсора бейдж (имя или «N элементов»).
Механизм — на pointer-событиях внутри страницы, тот же, что уже двигает вкладки и панели; подсказка над целью говорит, что произойдёт.
| цель | результат |
|---|---|
| другая файловая панель (любая машина или SSH-хост) | небольшое окно у места броска: «Переместить / Копировать / Отмена», куда (папка цели), «если уже есть: сообщить ▾». Внутри машины — fs.copy; внутри SSH-хоста — cp/mv; между разными — существующая передача tar с прогрессом в этом же окне |
| папка в списке панели | то же, цель — эта папка |
| терминал той же машины / того же SSH-хоста | пути в одинарных кавычках через пробел вставляются в терминал, без Enter |
| терминал другой машины | цель подсвечивается красным, подсказка «Нельзя: файл на X, терминал на Y» |
| заголовок вкладки | через 0,5 с наведения вкладка активируется, бросить можно в её панель |
| пустое место / Esc | отмена |
Правила конфликтов имён — те же, что в окне «Переместить или копировать». Загрузка из ОС перетаскиванием — в любую файловую панель. На телефоне перетаскивания нет; остаётся окно перемещения с выбором машины или SSH.
5. Окна машины
«Порты», «Статус», «Изменить» — нынешние страницы как фрагменты (?frag=1) в общем окне machinedlg (заголовок «машина · раздел», закрытие; на телефоне — на весь экран).
Открываются из кнопок строки в списке машин и из меню заголовка вкладки или панели (её машина). Формы — перехватом из части 1; результат (например, обновления клиента) показывается в окне.
Живые части (графики и опрос статуса, тест скорости, присутствие) — модули mount / unmount; при закрытии окна останавливаются.
Ошибки и крайние случаи
- Машина офлайн: терминал — как сейчас; файловая панель — «машина офлайн» и «повторить», при возвращении машины обновляется сама.
- Нет доступа (роль «пользователь»): чужих машин нет в меню и списке; если доступ отобран при открытой вкладке — панель показывает «нет доступа».
- Сессия истекла (401 или редирект на
/login): сообщение и переход на вход. - Агент без
sshfs.*: пункт «Файлы по SSH» сообщает «обновите агента». - Фрагмент не загрузился: ошибка и «повторить» в его области, остальное приложение работает.
- SSH-подключение файловой панели оборвалось: следующая операция переподключается один раз; не вышло — панель сообщает и предлагает переподключиться.
Проверка
На стенде (сервер, агент, тестовый sshd), Chrome на компьютере и в эмуляции телефона:
- Переходы Машины ↔ Терминал ↔ Настройки при идущем выводе в терминале — вывод не прерывается; «Назад / Вперёд»; перезагрузка — сброс и «Покинуть сайт?».
- Вкладки с терминалом, файлами, SSH-файлами; разделение, изменение размеров, перетаскивание панелей и вкладок.
- Файловая панель машины и SSH-хоста: список, просмотр, правка, загрузка, скачивание, создание, удаление, переименование, права.
- Перетаскивание: в соседнюю панель (своя машина, SSH), в папку, в терминал той же машины (вставка путей), в терминал чужой (запрет).
- Окна машины: формы, обновление клиента, остановка графиков при закрытии.
- Роли: обычный пользователь видит в меню и списке только свои машины.
- Регрессия: PIN, ключи доступа, установщик, редактор SQLite, перенос на другие машины, прямой адрес.
Версия и документация
Версия 0.2.0. README — разделы о рабочем пространстве, файлах по SSH и перетаскивании.