feat(node): package Ubuntu desktop setup and trusted access

This commit is contained in:
DCCONSTRUCTIONS
2026-09-05 17:27:59 +03:00
parent 57f2537af3
commit d696842f5d
52 changed files with 4457 additions and 0 deletions
@@ -0,0 +1,300 @@
# Mission Core Node: первый запуск борта
Основание: MISSIONCOR-76 и согласованные комментарии UI-FIRST / BRIDGE-ONLY.
Документ описывает реализацию первого приращения; тело архитектурной карточки
остаётся исходной точкой и не изменяется этим документом.
Ниже сохранена история bootstrap 0.1–0.2.3. Текущая композиция, результаты
проверки 0.3.0 и актуальные ограничения описаны в
[02_NODE_DESKTOP_SURFACE.md](02_NODE_DESKTOP_SURFACE.md).
## Пользовательская задача и размещение
Оператор устанавливает Node на Ubuntu и открывает приложение, чтобы убедиться,
что служба запущена, назвать борт и проверить фактические сетевые/USB подключения.
Первичная сущность — этот бортовой компьютер; его ID переживает смену имени,
IP и перезагрузку. Сетевой интерфейс и обнаруженный USB не означают готовность
сенсора к съёмке. Обновление списка ничего не отправляет устройствам.
Выбрана самостоятельная локальная поверхность Node, уже запрошенная владельцем:
ApplicationShell с предметным обзором в stage. Альтернатива — только инспектор
в разделе «Парк» Control Station — не решает первый запуск без сопряжённого Core.
Навигация Core и его существующие рабочие пространства не меняются. Это доменная
композиция из существующих ApplicationShell, AppHeader, HeaderWorkspace,
GlassSurface, TextField, Button, StatusBadge, ActivityIndicator и ToastStack;
новые общие компоненты или визуальные примитивы не вводятся. Лабораторная
композиция не используется. Отдельных окон/expanded modes у этого обзора нет.
Действия: запуск через меню ОС, подтверждение штатного диалога администратора,
чтение состояния, переименование с сохранением, обновление, выгрузка очищенного
отчёта, ввод и отзыв публичного SSH-ключа для локального администратора.
Состояния: ожидание, доступ разрешён, сеанс отсутствует/истёк, служба
недоступна, частично недоступная инвентаризация, сохранение, ошибка записи.
Ошибки запросов принадлежат ToastStack; фиктивной готовности и кнопок будущих
подключений нет. Обновление не показывает устаревшие данные как новые.
## Граница первого пакета
`apps/node-agent` — отдельное собираемое приложение внутри текущего монорепозитория.
Go-служба работает от непривилегированного системного пользователя. systemd
запускает её после перезагрузки; состояние в `/var/lib/mission-core-node`.
Установленное приложение открывается в собственном окне GTK со встроенным
WebKit, без внешней вкладки браузера и адресной строки. Общие React-компоненты
дизайн-системы отображаются внутри этого окна. Внутренний UI-служебный канал
доступен только через `127.0.0.1:8780` на борту. Это локальный UI
Node, а не второй экземпляр Control Station на 8000 и не endpoint сопряжения.
Адреса удалённых Node не принимаются этим локальным API.
Установка — `.deb` через графический установщик пакетов Ubuntu. При сборке
в бинарник включены JS/CSS, включая зависимости дизайн-системы; на борту не
нужны Node.js, npm, Go, исходники Core или соседний checkout дизайн-системы.
Системный установщик разрешает зависимости и запрашивает права через штатный UI.
По уточнению владельца «Конфигурация системы» включает установку OpenSSH Server
как обязательной зависимости, проверку `sshd -t`, включение `ssh.service` и
автозапуска. Интерфейс проверяет ответ SSH-2.0 на loopback: это проверка процесса,
не доказательство входа с другого компьютера. Публичные ключи Ed25519 вводятся
через TextAreaField, пользователь выбирается через Select, отзыв подтверждается
ConfirmationModal. Эти существующие общие компоненты дополняют список выше.
Ключи Node дополняют обычные Ubuntu authorized_keys через фиксированный,
принадлежащий root AuthorizedKeysCommand. Он читает только реестр публичных
ключей; отдельные процессы запускаются от пользователя службы, не root.
Регистрация ограничена существующими локальными пользователями группы sudo,
root исключён. Строки authorized_keys с command/options и приватные ключи не
принимаются. Выданные строки ограничены частными LAN/Tailscale адресами через
`from=`. Отзыв в Node не закрывает существующие SSH-сессии и не удаляет отдельные
ключи/методы входа Ubuntu. SSH не становится транспортом управления сенсорами.
Владелец открыл файл `.deb` версии 0.1.1, установил его через GUI и нашёл Node
в меню приложений. На Mini подтверждены статус installed, запуск окна из
`/usr/bin/mission-core-node`, активные и включённые службы Node/SSH. Это ещё не
полная приёмка на чистой Ubuntu: SSH ранее подготовлен для инженерного доступа,
проверка перезагрузки и отзыва отдельного SSH-ключа через Node ещё не пройдена.
Ярлык запускает непривилегированное окно приложения. Оно вызывает фиксированный
polkit helper, который только запрашивает одноразовый минутный допуск у службы
по Unix-сокету с правами 0600. URL с допуском загружается внутри окна приложения.
WebKit использует временный профиль; переходы на другие адреса и дополнительные
окна запрещены. Сохранение отчёта открывает системный диалог выбора файла.
Закрытие окна не завершает службу борта. Токен передаётся во fragment и
удаляется из истории до запроса. API обменивает его один раз на HttpOnly,
SameSite=Strict cookie на 8 часов. После перезапуска сеансы прекращаются.
Host/Origin/fetch-metadata проверки препятствуют управлению через чужой сайт.
Никаких ручных ключей, паролей в конфигурации или SSH для оператора.
Ed25519 identity создаётся при первом запуске и хранится с правами 0600. При
повреждённой identity запуск останавливается, другая identity молча не создаётся.
ID — полный SHA-256 публичного ключа. Это идентичность Node, не новый контракт
идентичности устройств: Plugin SDK v0alpha2 остаётся источником device contract.
Настройка имени не меняет ключ. Экспорт отчёта не содержит ключей, сессий, ID ноды,
hostname и сетевых адресов. Инвентаризация не читает USB serial.
## Что остаётся реализовать по базовой карточке
Этот пакет не является завершённым Node v1. Отдельными вертикальными сценариями
идут сопряжение Core с одноразовым приглашением и mTLS, Plugin SDK transport, D455, Linux K1 Bridge, управление
секретами устройств через UI, запись/импорт, WebRTC и восстановление.
Не добавлять их как пустые маршруты, готовые галочки или mock-устройства.
K1 Quick остаётся в прежнем лабораторном Mac-пути, не в Node.
K1 подключается только по Wi-Fi в режиме Bridge к общей локальной сети;
проводное подключение K1 не входит в план. D455 подключается к борту по USB.
## Инженерный доступ к текущему Mini
Владелец разрешил ручной SSH bootstrap для текущей разработки и размещение
полного репозитория в `Загрузки/NDC/MISSION_CORE` на Mini. Этот путь относится
к рабочему checkout, а не к обязательным путям устанавливаемого продукта.
Передача исходников и пакетов идёт по SSH/SFTP. Приватный ключ оператора остаётся
на его компьютере. Доступ обычного пользователя по SSH и административное
повышение прав проверяются отдельно: наличие группы sudo не означает, что
`sudo` доступен без подтверждения. Инженерный launcher может использовать
приватный сокет пользовательской службы; это не проверка установки с нуля.
Первый вход установил фактические Ubuntu 24.04.4 LTS amd64 и ядро
7.0.0-31-generic. Совместимость D455 следует проверять на этом ядре, не выводить
её из номера LTS. На Mini подтверждена D455 (8086:0b5c), подключение 5000 Мбит/с,
интерфейсы uvcvideo и usbhid. Владелец подтвердил отдельное окно приложения и
RealSense в его списке USB. Это приёмка отображения инвентаризации, не SDK/потоков.
После установки ярлык `org.nodedc.MissionCoreNode.desktop` совпадает с GTK
application ID для корректной регистрации окна в меню и панели Ubuntu.
Инженерный запуск из checkout не считается системной установкой приложения.
## Приращение 0.2.0: частная сеть и значок приложения
Владелец запросил чистый фирменный знак для значка Ubuntu. Пакет потребляет
`nodedc-mark.svg` из закреплённого Design Guideline; значок, desktop
entry и GTK application ID согласованы. Новая визуальная сущность не вводится.
В существующий обзор добавлена предметная секция «Удалённый доступ · Tailscale»
из GlassSurface, StatusBadge, Button и ActivityIndicator; ошибки операций
передаются в общий ToastStack. Новый экран или навигационный раздел не создаётся.
Оператор устанавливает компонент, подтверждает системное действие Ubuntu и
входит в свою сеть на странице провайдера в браузере. Состояние возвращается
в окно Node автоматически. Вход в Tailscale не означает сопряжения с Core.
Служба Node имеет только GET адаптер состояния Tailscale: без peer inventory,
учётных записей, AuthURL, ключей и необработанных сообщений провайдера. Изменения
выполняются двумя фиксированными root-owned polkit helpers, вызываемыми только
нативным мостом окна: установить и подключить. Команды, пути, сетевые параметры
и секреты из JavaScript не принимаются. Root helper запускает Python в isolated
mode, использует фиксированные команды и отдельную блокировку операций в
root-owned каталоге. Установка APT не прерывается закрытием окна посреди транзакции.
Для нового борта загружается официальный Tailscale 1.102.3 amd64 с закреплённой
SHA-256; несовпадение блокирует запуск APT. Пакет устанавливается без удаления
других пакетов, служба включается. Существующий установленный Tailscale не
переустанавливается; новый APT-репозиторий не добавляется. Первое подключение
не принимает DNS и subnet routes из tailnet; выход через exit node, публикация
подсетей, Tailscale SSH и принудительная повторная авторизация не включаются.
Остановленная существующая сеть возобновляется без флагов изменения настроек.
Нестандартная конфликтующая конфигурация не сбрасывается автоматически.
Допущен только URL входа HTTPS на login.tailscale.com с формой /a/…; он живёт
в памяти нативного процесса и открывается обычным браузером пользователя.
Node не собирает пароль провайдера и не журналирует его URL входа. API состояния
показывает только локальные адреса, состояние провайдера и Online. При закрытии
или удалении Node отдельная служба Tailscale сохраняется. Замена провайдера
сети не должна менять Node identity, Plugin SDK или локальную жизнь устройств.
При обновлении 0.1.1 → 0.2.0 требуется повторное открытие окна. Возможность
сетевой настройки объявляется нативной оболочкой; старое окно после обновления
показывает понятную подсказку вместо неподдерживаемых активных кнопок.
Приёмка этого приращения пока ожидается на Mini: установить новый файл .deb
через GUI, запустить из меню и проверить логотип, выполнить установку
Tailscale кнопкой, пройти вход в браузере и увидеть фактическое «В сети» в Node.
Отдельно проверить отмену OS-auth, повторное открытие окна и сохранность доступа
к прежней LAN. Дальше — перезагрузка и UI-сценарий SSH enrollment/revoke.
## Выявленные ограничения установки 0.2.0 (2026-09-05)
Владелец проверил обновление поверх 0.1.1: установленный на Mini App Center
revision 1270 показал «установлено» и не предложил обновление локальным файлом.
Предыдущая рекомендация просто открыть новый .deb для обновления не прошла
пользовательскую проверку. Этот путь нельзя считать готовым; требуется отдельно
довести и принять обновление через интерфейс без ручного удаления приложения.
После успешного удаления через Synaptic повторная установка 0.2.0 останавливалась
до распаковки. В журнале App Center зафиксирован PackageKit.cannotGetLock:
`/var/lib/dpkg/lock-frontend` занят оставшимся открытым Synaptic. Каждая попытка
завершалась отказом примерно через 10 секунд, интерфейс возвращал «Установить».
Проверка хеша файла успешна; APT simulation планирует только установку Node 0.2.0,
без удаления других пакетов. Это диагностика, не доказательство установки.
Временная процедура повторного прогона: выйти из Synaptic через «Файл → Выход»,
повторить «Установить» в App Center, затем проверить пакет, службу и запуск окна.
Не удалять lock-файлы и не прерывать выполняющуюся пакетную транзакцию.
В требования пользовательской приёмки входят понятное сообщение о занятом
менеджере пакетов, повтор после освобождения блокировки, обновление и удаление
через UI. Удаление Node сохраняет identity; переустановка не равна чистой Ubuntu.
Повтор после закрытия Synaptic успешен: владелец подтвердил установку,
PackageKit завершил install-files успешно, dpkg сообщает install ok installed
0.2.0, служба Node active. Пакет не требовал пересборки для устранения блокировки.
## Исправление значка 0.2.1
Владелец сообщил об искажённых пропорциях иконки после установки 0.2.0.
Штатный Gtk.IconTheme на Mini загружал исходный SVG как прямоугольный pixbuf
64×38 даже с FORCE_SIZE. В 0.2.1 build_deb.py оборачивает неизменённый брендовый
SVG квадратным прозрачным SVG 256×256 с сохранением пропорций. SHA-256 исходного
знака по-прежнему проверяется; его геометрия и цвет не меняются.
Проверка тем же GTK на Mini даёт квадратные pixbuf 32, 48, 64, 128 и 256 пикселей;
видимая область на 256×256 — 256×150, что соответствует исходному отношению
93.22:54.55 с округлением растеризации. PNG 256×256 визуально проверен.
Встроенный UI переиспользуется из проверенной сборки 0.2.0. Бинарник Go собирается
с номером текущего пакета через linker flag, чтобы версия в интерфейсе не отставала.
Обновление через системное окно авторизации в инженерном
сеансе не заменяет ещё не принятую установку/обновление одним файлом для оператора.
## Исправление транспорта Tailscale 0.2.2
Две авторизации через браузер регистрировали Mini на стороне Tailscale, но
локальная служба оставалась NeedsLogin без адресов и сохранённого профиля.
После успешной регистрации machineAuthorized=true следовали повторные тайм-ауты
PollNetMap. TCP 80 показывал 1713 байт в Send-Q, повторные передачи и отсутствие
подтверждений. Это фактическое незавершённое подключение, а не устаревший статус
Node. UDP/IPv4 netcheck успешен. Причина потери пакетов внутри внешней сети
не установлена; утверждать конкретного провайдера/фильтр по этим данным нельзя.
Встроенная диагностика Tailscale debug ts2021 с TS_FORCE_NOISE_443=true успешно
прошла TLS, Noise handshake и whoami через TCP 443. Возможность проверена по
исходникам установленного Tailscale v1.102.3 control/controlhttp/client.go.
0.2.2 объединяет квадратный значок и применение HTTPS-транспорта провайдера
через /etc/systemd/system/tailscaled.service.d/60-mission-core-node-https.conf.
Новая установка компонента применяет настройку перед входом. Явное действие
подключения восстанавливает ещё не подключённую службу с этим транспортом;
уже работающая или ожидающая одобрения служба не перенастраивается. Реальное
окружение daemon проверяется только на нужный несекретный флаг, без вывода
окружения. Чужой файл/симлинк/небезопасные права приводят к отказу с сохранением
существующих настроек. Удаление Node сохраняет самостоятельную службу Tailscale
и её транспорт; ключи, профили, DNS, exit node и маршруты helper не редактирует.
8 Python-проверок прошли, включая сохранение работающего провайдера,
восстановление без нового входа при наличии профиля и отказ при конфликте
эффективных настроек. Владелец затем подтвердил реальный вход через UI:
«В сети» и адрес Tailscale. Независимый status на Mini — Running, Online=true,
адреса назначены; TSMP ping до компьютера оператора идёт напрямую по LAN за 5 мс.
Это ещё не приёмка TCP/SSH через tailnet: отдельная попытка SSH не завершилась.
Промежуточный пакет 0.2.1 со значком заменён этим кандидатом до установки.
## Восстановление UI-сеанса 0.2.3 и настройка владельца
При обновлении службы ранее открытое окно сохраняло старый сеанс. Polling в
TailnetAccess поглощал HTTP 401 как общее «Состояние недоступно», хотя причина
относилась к доступу в Node. Теперь 401 передаётся существующему обработчику
приложения: сведения убираются, показывается штатная поверхность входа.
Это не изменение сетевого статуса Tailscale и не обход авторизации.
Проверка через интерфейс: временный Node 0.2.3-qa на Mac, вход, перезапуск только
тестовой службы с сохранением identity и новым набором сеансов, автоматическое
появление поверхности входа на очередном polling. Тестовый процесс и вкладка
закрыты. TypeScript, Node UI boundary, 4 архитектурные проверки и production build
успешны. Пакет 0.2.3 передан на Mini; его подтверждение после обновления и
переоткрытия окна фиксируется отдельно от лабораторной проверки.
Владелец отдельно и явно выбрал отключение запросов административного пароля
для своего активного локального сеанса во всей Ubuntu. Подготовлено персональное
правило Polkit: конкретный пользователь владельца, local=true, active=true,
членство sudo, результат YES. Оно относится к графическим действиям через Polkit;
sudoers, SSH-аутентификация, вход в ОС и блокировка экрана не изменяются.
Это персональная настройка текущего Mini, не значение по умолчанию пакета Node
для остальных операторов. Правило расширяет права приложений локального сеанса;
владелец выбрал этот режим после уточнения области действия.
Сценарий применения находится в Загрузки/NDC/.setup/mc-node-owner-setup.py на Mini:
проверяет SHA-256 конкретного .deb, обновляет Node до 0.2.3, проверяет установленную
версию и только после этого атомарно публикует root-owned правило Polkit.
Чужой файл в целевом пути сохраняется с отказом. После ввода пароля в системном
окне и переоткрытия Node владелец 2026-09-05 явно подтвердил через интерфейс:
«0.2.3, в сети, без пароля». Это подтверждает версию окна, статус Tailscale и
открытие Node без повторного запроса пароля. Все остальные административные
действия Ubuntu этим сценарием не проверены. Независимая окончательная проверка
установленного пакета и файла правила ещё не выполнена: SSH к Mini обрывается
до авторизации. Восстановление инженерного SSH остаётся открытым пунктом.
## Приёмка с нуля
Инженерные тесты проверяют защиту API, сохранность identity и очистку отчёта.
Они не заменяют следующую пользовательскую приёмку на реальной Ubuntu:
1. На чистой согласованной Ubuntu без подготовленных SSH/ключей открыть пакет.
2. Установить через GUI и найти Mission Core Node в меню приложений.
3. Открыть, подтвердить системный запрос, получить фактические данные именно Mini.
4. Изменить название; закрыть окно приложения, открыть снова, проверить сохранение и ID.
5. Перезагрузить Mini; повторить запуск, проверить автозапуск и неизменный ID.
6. Подключить/отключить D455 через USB и обновить список; не выдавать enumeration
за рабочий поток и не считать USB 2 достаточным для D455.
7. Сохранить и проверить очищенный отчёт через системный диалог; проверить
закрытие/повторное открытие окна, повторную авторизацию и истечение сеанса.
Отдельно проверить отсутствие доступа к внутреннему адресу через браузер
без авторизации и невозможность входа повторным URL.
8. Проверить клавиатуру, отмену системного запроса, ошибку службы и повторный запуск.
9. Проверить SSH на чистой Ubuntu: установка зависимости, перезагрузка, живой
ответ, ввод публичного ключа через UI, реальный вход с частного адреса,
отзыв через UI и отказ в новом соединении. Отдельно проверить несовместимую
существующую конфигурацию sshd: не подменять её молча и не заявлять доступ
только на основании сохранённого ключа.
До выполнения этих пунктов на Mini первый пакет остаётся кандидатом для проверки.
+106
View File
@@ -0,0 +1,106 @@
# Node 0.3 — структура настольного приложения
Решение владельца от 2026-09-05: привести доступные функции Node к визуальной
системе действующего Mission Core, повторно использовать шапку, навигацию и
длинные строки AI Inference. Это согласование состава вкладок и композиции.
Базовые архитектурные требования карточки MISSIONCOR-76 не изменяются.
## Задача оператора
На бортовом компьютере проверить систему и оборудование, подключить частную
сеть и разрешить обслуживание с нескольких доверенных компьютеров. Сценарий
начинается с запуска установленного приложения, используется при первичной
настройке и обслуживании. Объекты: этот борт, его интерфейсы/USB и список
разрешённых публичных SSH-ключей. Управление съёмкой не добавляется.
## Размещение
Выбрана предложенная владельцем структура:
- Состояние системы: обзор компьютера, сеть, конфигурация системы, диагностика.
- Устройства: существующее обнаружение USB.
- Удалённый контроль: Tailscale и SSH / доверенные устройства.
Верхние вкладки — HeaderNavigation. Подразделы — AdminNavigationPanel.
Контент — ApplicationPanel в ApplicationShell. Открытие, закрытие, разворот
и узкий экран принадлежат useApplicationWorkspace. Общая сетка всех функций
отклонена: смешивала инвентаризацию, настройку транспорта и выдачу доступа.
Лабораторный отчёт как шаблон Node также отклонён: здесь изменяемые объекты и
действия оператора. Из LAB используется только уже существующий список.
VPN-профили не появляются пустым пунктом: их провайдер пока не реализован.
## Повторное использование
Node уже использовал React и пакеты Design Guideline. Теперь подключён полный
канонический shell без конвертации изображения или копии CSS шапки. GTK/WebKit
остаётся установленным настольным контейнером; React-сборка входит в .deb.
Сервер слушает только loopback. Браузерная QA не заменяет настольную приёмку.
Компоненты: AppHeader, HeaderWorkspace, HeaderNavigation, HeaderProfile,
UserProfileMenu, ApplicationShell, ApplicationPanel, AdminNavigationPanel,
SettingsCard, Icon/IconButton/Button, Window/ConfirmationModal, Select,
TextField/TextAreaField, ActivityIndicator, StatusBadge, ToastStack.
Семантические иконки взяты из registry/icons.json.
ResourceRow/ResourceList сначала выделены в Design Guideline из существующей
геометрии observatory-evidence-card. Добавлены export, registry, документация
и пример каталога. Состояния и действия остаются у потребителя. Старые строки
AI Inference не меняются этим приращением; их миграция на общий export —
отдельное изменение Core. Точные исходники и dist DG хэшируются в provenance,
поскольку локальный общий компонент ещё не является опубликованным релизом.
## Действия и состояния
SSH: плюс в шапке открывает добавление, выбор существующего администратора,
название устройства и вставка публичного Ed25519. Разрешено несколько ключей;
приватный ключ остаётся на компьютере оператора. Подробности показывают полный
отпечаток и публичный ключ. Отзыв требует ConfirmationModal и запрещает только
новые подключения через Node. Статус ключа не означает online компьютера.
Локальный ответ sshd не означает успешный удалённый вход.
Обзор сохраняет имя и показывает системные сведения с временем получения.
USB показывает обнаружение, без обещания готовности к съёмке. Tailscale
сохраняет действующий поллинг и обработку истёкшего сеанса. Все списки имеют
loading, empty, unavailable и recovery через обновление; ошибки — ToastStack.
Добавление и удаление блокируются на время запроса. Нет консольных команд и
отладочных механизмов в операторском интерфейсе.
## Приёмка
Проверить собранный React-интерфейс через UI: каждую вкладку и подраздел,
разворот/возврат, добавление/подробности/отмену/отзыв SSH на изолированной QA-ноде,
rename, ошибки и повторное открытие, Tailscale online/expired session.
Проверить темы и узкий экран; затем новый .deb на Mini, сохранение identity,
списка доверенных ключей и текущего входа Tailscale. Реальный удалённый SSH и
чистая Ubuntu — самостоятельные пункты приёмки.
## Результат проверки 2026-09-05
Пройдены UI-сценарии на изолированной QA-ноде с настоящим API Node и отдельным
хранилищем: обзор/сеть/конфигурация/диагностика/USB/Tailscale/SSH, сохранение имени,
неверный ключ с сохранением draft, добавление синтетического публичного ключа,
полные сведения, Escape с возвратом фокуса, отмена и подтверждение отзыва.
Успешная операция заменяет предыдущее сообщение об ошибке. Проверены dark/light,
узкое окно 720×800, сворачивание и разворот. После рестарта тестовой службы
поллинг Tailscale переводит приложение на вход; ошибочный сетевой статус не
подставляется. Первый запрос Tailscale теперь имеет отдельное состояние загрузки.
При QA исправлены два общих дефекта Design Guideline: на узком экране скрывается
expand по типу действия, а не первая кнопка шапки; одноцветные светлые знаки
могут явно включить контраст для light theme. Цветные изображения по умолчанию
не меняются. Геометрия ResourceRow проверена в обоих режимах.
Typecheck всех пакетов DG и каталога, registry validation, production build
каталога и Node, 4 архитектурных теста Core и Node UI boundary прошли.
Готовый .deb установлен на Mini до 0.3.0. После обновления независимо проверены
работающий Tailscale, D455 USB3 и запуск нового настольного процесса. Пользовательская
визуальная приёмка именно окна Ubuntu запрошена отдельно. Через временный
loopback SSH-туннель дополнительно проверен UI именно установленного Mini:
версия 0.3.0, реальные сведения о системе, Tailscale «В сети», SSH отвечает
локально, реальная D455 со скоростью 5000 Мбит/с. Туннель и QA-процессы закрыты. Все синтетические
SSH-ключи находятся только в QA-хранилище и не дают доступа к настоящему Mini.
Инженерный SSH к Mini снова работает по Tailscale с проверкой прежнего ключа
хоста. Прямой LAN-путь не квалифицирован; причина прежнего обрыва не доказана.
Чистая установка Ubuntu, перезагрузка борта, GUI updater/uninstaller и реальное
зачисление/отзыв ключа оператора остаются отдельными пунктами общей приёмки.