ADR 0203 — Поток runner через браузер выводится из употребления, путь — установщик
Статус
Accepted. 2026-10-01 (AT-014, BRB-031, раунд 36; решение владельца от
01.10: «вывести из употребления поток браузера из ADR 0118 — генерацию ключа, загрузку
бинарника и запись config через браузер; путь — install.sh»).
Пересматривает, не редактируя,
ADR 0118
(автоматическая настройка runner через браузер, RN-464..466) и закрывает
BRB-031. Сохраняет ADR 0154 (два
вида ключа), ADR 0155
(ключ машины рождается в терминале, и установщик его регистрирует, RN-547/551/552)
и ADR 0150 (однострочный установщик и
проверка собственного происхождения).
Контекст
ADR 0118 заставил браузер генерировать пару Ed25519 (Web Crypto), регистрировать
публичный ключ (POST /projects/:projectId/runner-device-keys), скачивать бинарник
(GET /runner-releases/binary) и записывать три файла в папку через File
System Access API — или, вне Chromium, запускать две загрузки. Он письменно принял
ограничение: «браузер не сохраняет бит выполнения;
chmod +x в Linux/macOS остаётся ручным». Это был последний ручной шаг
любого пути установки, и это BRB-031.
ФАЗА 29 создала второй путь без этого шага: install.sh скачивает
бинарник, сверяет его с подписанным checksums.txt и устанавливает его через
install -m 0755 (RN-531). ФАЗА 30 завершила спаривание со стороны
машины: brabo-runner device-key create генерирует пару НА МАШИНЕ (RN-551),
установщик регистрирует публичный ключ через внутренний маршрут МАШИНЫ с service token
(RN-552) и связывает обе вещи в конце установки (RN-547). С тех пор
поток браузера был вторым путём, свёрнутым в <details>
RunnerOnboardingPanel (RN-548), а его вывод из употребления остался объявленным как решение
сопровождающего, а не следствие той поставки.
Измерено в dev (ec0fbea52d) до изменения — кто использует то, что использует поток:
- У
apps/web/src/lib/runner-bootstrap.ts(генерация пары, экспорт JWK, загрузка бинарника, запись папки, ручной набор) был один production-потребитель,RunnerOnboardingPanel. Вне его — только собственный тест иscripts/ci/alvos-do-runner.spec.ts, который читал список платформ браузера как четвёртое место, перечисляющее цели. registerRunnerDeviceKey(apps/web/src/lib/api-client.ts) вызывался только изrunner-bootstrap.ts.POST /projects/:projectId/runner-device-keysвызывался только изrunner-bootstrap.tsи изe2e/testes/chave-de-dispositivo.spec.ts, который существовал, чтобы доказать ИМЕННО ключ, сгенерированный в Chromium. Ни один скрипт, ни один runner, ни один workflow, ни одинinstall.shего не вызывает — установщик используетPOST /internal/machine-device-keys.- У
GETиDELETEтого же маршрута есть ДРУГИЕ потребители: раздел ключей Настроек (RN-561), распознавание панели (RN-548) и отзыв. PatAuthGuardпринимает ключ ПРОЕКТА поkid, и в реальных установках есть ключи проекта, зарегистрированные потоком браузера.- У
GET /runner-releases/binary(proxy загрузки) единственным production-потребителем был браузер.
Решение
RunnerOnboardingPanelотправляет кinstall.sh. Первым планом панели становится команда установщика (curl -fsSLO …/install.sh && bash install.sh, ТА ЖЕ фраза из runbook и самогоinstall.sh, RN-526), копируемая, с текстовым описанием того, что она делает — скачивает бинарник, сверяет с подписанным манифестом, устанавливает уже исполняемым и спаривает машину, — иEsperaDoRunner(RN-474) под ней. Команда — копия на TS фразы установщика, иscripts/dev/install-invocacao.spec.tsотклоняет копию, которая разойдётся.- Что ОСТАЁТСЯ в панели: распознавание уже спаренного ключа (RN-548 и
ключа ПРОЕКТА, AT-107), с теми же оговорками, — и, когда распознан ключ,
обслуживающий проект, блок установщика УХОДИТ. Ручная команда с PAT
(
--token) остаётся в<details>, переименованном под случай, который она решает: «Outra máquina, ou rodar manualmente». - Что ИСЧЕЗАЕТ из web:
runner-bootstrap.tsцеликом и его тест (генерация ключа через Web Crypto, загрузка бинарника браузером, запись через File System Access и набор из двух загрузок),registerRunnerDeviceKeyи типRunnerDeviceKeySummary, ключи i18n кнопок и состояний потока и селектор платформы. - Что ИСЧЕЗАЕТ из api:
POST /projects/:projectId/runner-device-keys, вместе сRegisterRunnerDeviceKeyUseCaseи двумя DTO, принадлежавшими только ему. Он остался без вызывающего. Внутренний маршрут МАШИНЫ (POST /internal/machine-device-keys) ОСТАЁТСЯ, и линейка формы JWK (exigirJwkPublicaEd25519, в домене) остаётся с ним. - УЖЕ зарегистрированный ключ проекта продолжает действовать и может быть отозван. В
базе ничего не меняется: заполненный
runner_device_keys.project_idостаётся допустимым видом,PatAuthGuardпродолжает принимать подписанный им JWT,GETпродолжает перечислять, аDELETE— отзывать. Runner, настроенный через браузер до этого ADR, не ломается: папка сbrabo-runner.config.jsonиbrabo-runner-device-key.jwk.jsonпо-прежнему читается CLI (RN-466 целиком), и unit ПРОЕКТА, которую он мог установить, продолжает работать. Перестаёт существовать создание НОВОГО ключа проекта. - e2e ключа, сгенерированного в браузере, уходит вместе с ним. То, что он доказывал, —
что
kid, записанный БРАУЗЕРОМ, принимается сервером, — больше не имеет производителя. Цепочкаkid→ JWT →PatAuthGuardс реальным ключом по-прежнему покрыта вapps/api/test/interfaces/pat-auth.guard.spec.ts, а пара, сгенерированная на машине, — вapps/runner/src/criar-chave-de-dispositivo.spec.ts. - Список целей runner начинает жить в ТРЁХ местах, а не в четырёх:
список браузера ушёл вместе с модулем, и
scripts/ci/alvos-do-runner.spec.tsне даёт ему молча вернуться.
Ветка — breaking/: удаление публичного маршрута, задокументированного в OpenAPI, — это
изменение контракта для тех, кто его вызывает, а политика версий
(scripts/ci/version.ts) говорит, что решает ФУНКЦИЯ, — patch сказал бы «обновляйте
не думая».
Последствия
Хорошие.
- У пути установки больше нет ручного шага
chmodнигде в продукте: единственный, у которого он был, ушёл.BRB-031закрывается. - НОВЫЙ ключ устройства рождается в одном месте — терминале машины — и регистрируется одним регистратором — установщиком. api теряет маршрут записи, аутентифицируемый JWT сессии.
- Web теряет ~530 строк кода криптографии, загрузки и записи на диск, которые jsdom не мог проверить без дублёра.
Плохие, объявленные.
- Установка с командой теряет путь без PAT. Маршрут, создающий ключ
МАШИНЫ, обслуживает только установку ОДНОГО человека (409 при двух и более, RN-552), а
install.shустанавливает весь Brabo на машину — он не годится для спаривания ВТОРОЙ машины с уже существующей установкой. Для этих людей путь становится ручной командой с PAT (--token), которую панель продолжает предлагать и называет путём для другой машины. Поток браузера был единственным способом спарить без PAT в этом случае, и решение владельца всё равно выводит его из употребления. GET /runner-releases/binaryостаётся без production-потребителя. Proxy НЕ был удалён здесь: решение назвало маршрут регистрации ключа, а proxy несёт проверку целостности RN-525 и открытую половину происхожденияBRB-005. Удалить или оставить — решение владельца, отдельное.- Тот, у кого была открыта вкладка потока в момент деплоя, получает 404 на
POSTпри клике — старый bundle всё ещё вызывает маршрут. Перезагрузка страницы решает это. - RN 464..466 и 473/475 описывают поток таким, каким он был; они получают пометку о пересмотре, никогда не удаление.