ADR 0203 — O fluxo do runner pelo navegador é aposentado, e o caminho é o instalador
Status
Accepted. 2026-10-01 (AT-014, BRB-031, rodada 36; decisão do dono em
01/10: "aposentar o fluxo do navegador do ADR 0118 — gerar chave, baixar
binário e gravar config pelo navegador; o caminho é o install.sh").
Revisa, sem editá-lo, o
ADR 0118 (a
configuração automática do runner pelo navegador, RN-464..466) e fecha o
BRB-031. Preserva o ADR 0154 (as
duas espécies de chave), o ADR 0155
(a chave de máquina nasce no terminal e o instalador a registra, RN-547/551/552)
e o ADR 0150 (o instalador de uma linha e a
verificação da própria origem).
Context
O ADR 0118 fez o navegador gerar o par Ed25519 (Web Crypto), registrar a
pública (POST /projects/:projectId/runner-device-keys), baixar o binário
(GET /runner-releases/binary) e gravar três arquivos numa pasta pela File
System Access API — ou, fora do Chromium, disparar dois downloads. Ele aceitou
uma limitação por escrito: "o navegador não preserva o bit de execução;
chmod +x em Linux/macOS continua manual". Era o último passo manual de
qualquer caminho de instalação, e é o BRB-031.
A FASE 29 criou um segundo caminho sem esse passo: o install.sh baixa o
binário, o confere contra o checksums.txt assinado e o instala com
install -m 0755 (RN-531). A FASE 30 completou o pareamento do lado da
máquina: brabo-runner device-key create gera o par NA MÁQUINA (RN-551), o
instalador registra a pública pela rota interna de MÁQUINA com o service token
(RN-552) e encadeia as duas coisas no fim da instalação (RN-547). Desde então o
fluxo do navegador era o segundo caminho, recolhido num <details> do
RunnerOnboardingPanel (RN-548), e aposentá-lo ficou declarado como decisão do
mantenedor, não consequência daquela entrega.
Medido em dev (ec0fbea52d) antes de mudar — quem usa o que o fluxo usa:
apps/web/src/lib/runner-bootstrap.ts(gerar par, exportar JWK, baixar binário, gravar pasta, kit manual) tinha um consumidor de produção, oRunnerOnboardingPanel. Fora dele, só o próprio teste escripts/ci/alvos-do-runner.spec.ts, que lia a lista de plataformas do navegador como o quarto lugar que enumera alvos.registerRunnerDeviceKey(apps/web/src/lib/api-client.ts) só era chamado porrunner-bootstrap.ts.POST /projects/:projectId/runner-device-keyssó era chamado porrunner-bootstrap.tse pore2e/testes/chave-de-dispositivo.spec.ts, que existia para provar EXATAMENTE a chave gerada num Chromium. Nenhum script, nenhum runner, nenhum workflow, nenhuminstall.sha chama — o instalador usaPOST /internal/machine-device-keys.GETeDELETEda mesma rota têm OUTROS consumidores: a seção de chaves das Configurações (RN-561), o reconhecimento do painel (RN-548) e a revogação.PatAuthGuardaceita chave de PROJETO porkid, e há chaves de projeto registradas em instalações reais pelo fluxo do navegador.GET /runner-releases/binary(o proxy do download) só tinha o navegador como consumidor de produção.
Decision
- O
RunnerOnboardingPanelmanda para oinstall.sh. O primeiro plano do painel passa a ser o comando do instalador (curl -fsSLO …/install.sh && bash install.sh, a MESMA frase do runbook e do próprioinstall.sh, RN-526), copiável, com o que ele faz dito em texto — baixa o binário, confere contra o manifesto assinado, instala já executável e pareia a máquina — e aEsperaDoRunner(RN-474) embaixo. O comando é uma cópia em TS da frase do instalador, escripts/dev/install-invocacao.spec.tsreprova a cópia que divergir. - O que FICA no painel: o reconhecimento de chave já pareada (RN-548 e o
da chave de PROJETO, AT-107), com as mesmas ressalvas — e, reconhecida uma
chave que serve o projeto, o bloco do instalador SAI. O comando manual com
PAT (
--token) fica no<details>, renomeado para o caso que ele resolve: "Outra máquina, ou rodar manualmente". - O que SOME do web:
runner-bootstrap.tsinteiro e o teste dele (geração de chave pelo Web Crypto, download do binário pelo navegador, gravação via File System Access e o kit de dois downloads),registerRunnerDeviceKeye o tipoRunnerDeviceKeySummary, as chaves de i18n dos botões e estados do fluxo, e o seletor de plataforma. - O que SOME da api: o
POST /projects/:projectId/runner-device-keys, comRegisterRunnerDeviceKeyUseCasee os dois DTOs só dele. Ele ficou sem chamador. A rota interna de MÁQUINA (POST /internal/machine-device-keys) FICA, e a régua de forma da JWK (exigirJwkPublicaEd25519, no domínio) fica com ela. - Chave de projeto JÁ registrada continua valendo, e é revogável. Nada no
banco muda:
runner_device_keys.project_idpreenchido continua sendo uma espécie válida,PatAuthGuardcontinua aceitando o JWT assinado por ela, oGETcontinua listando e oDELETEcontinua revogando. Um runner configurado pelo navegador antes deste ADR não quebra: a pasta combrabo-runner.config.jsonebrabo-runner-device-key.jwk.jsoncontinua sendo lida pelo CLI (RN-466 inteira), e a unit de PROJETO que ele tenha instalado continua de pé. O que deixa de existir é criar uma chave de projeto NOVA. - O e2e da chave gerada no navegador sai junto. O que ele provava — que o
kidgravado pelo NAVEGADOR é aceito pelo servidor — não tem mais produtor. A cadeiakid→ JWT →PatAuthGuardcom chave real segue coberta emapps/api/test/interfaces/pat-auth.guard.spec.tse o par gerado na máquina emapps/runner/src/criar-chave-de-dispositivo.spec.ts. - A lista de alvos do runner passa a morar em TRÊS lugares, não quatro: a
do navegador saiu com o módulo, e
scripts/ci/alvos-do-runner.spec.tstrava que ela não volte calada.
A branch é breaking/: remover uma rota pública documentada na OpenAPI é
mudança de contrato para quem a chama, e a política de versão
(scripts/ci/version.ts) diz que a FUNÇÃO decide — um patch diria "atualize
sem pensar".
Consequences
Boas.
- O caminho de instalação não tem mais passo manual de
chmodem lugar nenhum do produto: o único que tinha saiu.BRB-031fecha. - A chave de dispositivo NOVA nasce num lugar só — o terminal da máquina — e é registrada por um registrador só — o instalador. A api perde uma rota de escrita autenticada por JWT de sessão.
- O web perde ~530 linhas de código de cripto, download e escrita em disco que jsdom não conseguia exercitar sem dublê.
Ruins, declaradas.
- Instalação com time perde o caminho sem PAT. A rota que cria chave de
MÁQUINA só serve instalação de UMA pessoa (409 com duas ou mais, RN-552), e
o
install.shinstala o Brabo inteiro numa máquina — não serve para parear uma SEGUNDA máquina com uma instalação que já existe. Para essas pessoas o caminho passa a ser o comando manual com PAT (--token), que o painel continua oferecendo e nomeia como o da outra máquina. O fluxo do navegador era a única forma de parear sem PAT nesse caso, e a decisão do dono o aposenta mesmo assim. GET /runner-releases/binaryfica sem consumidor de produção. O proxy NÃO foi removido aqui: a decisão nomeou a rota de registro de chave, e o proxy carrega a verificação de integridade da RN-525 e a metade de procedência aberta doBRB-005. Remover ou manter é decisão do dono, à parte.- Quem tinha a aba do fluxo aberta no momento do deploy recebe 404 no
POSTao clicar — o bundle velho ainda chama a rota. Recarregar a página resolve. - As RNs 464..466 e 473/475 descrevem o fluxo como era; ganham nota de revisão, nunca apagamento.