ADR 0161 — A tela só oferece o modo que a instalação executa, e a instalação por Release não tem broker
Status
Accepted. Decidido pelo mantenedor em 2026-09-18 (AT-085), com a resposta "os dois" à pergunta "o instalador liga o broker, ou a tela para de oferecer o que não roda?". Revisa a pré-seleção da RN-513 (ADR 0146, ponto 4) e acrescenta um motivo de recusa local à RN-521. Nenhum dos dois é editado; este documento os referencia. Só a metade de TELA foi entregue — a metade do instalador foi medida e parou, pelo motivo da seção "A metade que parou".
Context
Uma instalação real da v6.1.0, feita pelo one-liner em 2026-09-14, criou pela
web um projeto em mounted. Ele foi o modo pré-selecionado: o install.sh
sempre grava BRABO_PROJECTS_BASE (a base consentida, RN-531),
e com base conhecida a RN-513 pré-seleciona
mounted. O que se seguiu no event log:
- 6×
dev.started→ 6×dev.blocked_by_container; - 2×
container.start_failedcom "BROKER_URL não está definida — o broker de container não faz parte desta instalação…".
Ninguém trabalha naquele projeto, para sempre. container e mounted só sobem
container pelo BROKER (ADR 0144), e sem
container running nenhum comando de dev agent roda
(ADR 0143). Só runner não
depende dele: quem sobe o container é o agente local, na máquina do usuário
(ADR 0137). E a página
/containers deixou aprovar as duas container_start que só podiam falhar.
Medido, e diferente da descrição da atividade: o compose de instalação não
"herdou o broker sob profile desligado". O serviço broker não existe em
docker/docker-compose.install.yml — o cabeçalho dele diz isso no ponto 3 —,
e a ausência foi decidida por escrito na decisão 7 do
ADR 0150, que também a declarou "na saída do
instalador". O defeito não é o instalador esconder a ausência: é a TELA não
saber dela, e oferecer — pré-selecionar, até — o modo que a ausência inutiliza.
A metade que parou: o instalador não consegue obter a imagem do broker
A decisão do mantenedor tinha uma parte (a): o install.sh perguntar se liga o
broker, com o risco dito em texto (o socket do Docker montado num serviço é
root-equivalente no host). Antes de escrever a pergunta, mediu-se se a
instalação consegue ter a imagem que a resposta "sim" subiria. Não consegue:
docker-bake.hcltem quatro alvos (api,engine,web,backup);scripts/ci/images-manifest.tsnão conhecebroker; e oimages.jsonda Release v6.1.0 lista exatamente essas quatro;docker manifest inspect ghcr.io/daneiel/brabo-broker:6.1.0respondedenied(o repositório não existe), enquanto o MESMO comando anônimo paraghcr.io/daneiel/brabo-api:6.1.0resolve — não é falta de credencial;- os assets da Release v6.1.0 não trazem
docker/broker/Dockerfile.prodnem o código deapps/broker/packages/docker-port, então uma instalação por one-liner, que roda numa pasta sem checkout (ADR 0160), não tem nem o que construir.
Uma pergunta cujo "sim" não tem imagem para subir é pior do que nenhuma: a
pessoa consente com o risco do socket e recebe um pull access denied. Só
--source=local (checkout limpo, em tag) poderia construir o broker — e mesmo
ali o compose de instalação não tem o serviço. A correção é a que o ADR 0150
já nomeou como pequena e fora do escopo dele: publicar o broker como quinta
imagem (um alvo no bake, um id no manifesto, uma assinatura a mais), e SÓ
DEPOIS a pergunta do instalador. Fica para frente própria, e é ela que reabre
esta metade. O install.sh não foi tocado por este ADR.
Decision
1. A api diz se a instalação tem broker, nas duas rotas que a tela já lê
brokerConfigurado: boolean entra em duas respostas existentes e em
nenhuma rota nova:
GET workspaces/:workspaceId/projects-base— a pergunta do assistente de criação já era "que modo esta INSTALAÇÃO consegue executar?", e a base era só metade dela. Mesmo mínimo (maintainer), mesmo chamador, mesmo instante;GET workspaces/:workspaceId/containers— por LINHA, com o mesmo valor em todas. A resposta é uma lista, e trocá-la por envelope quebraria o contrato por um campo que é da instalação.
A fonte é ContainerBrokerPort.configurado(), a MESMA que decide se a leitura
do estado observado pergunta ao broker ou declara ausência — ler BROKER_URL
uma segunda vez seria a segunda fonte que um dia diverge. O campo diz que a
variável EXISTE, nunca que o broker RESPONDE: quem sabe disso continua sendo
naoObservado (RN-486).
2. O assistente não pré-seleciona mounted sem broker, e oferece runner
Três estados, que não colapsam:
- broker confirmado (
true): comportamento da RN-513 intacto — com base,mountedpré-selecionado; - ausência confirmada (
false):containeremountedcontinuam NA TELA (tirar o card esconderia a informação — a régua "tira-se o controle, nunca a informação" da RN-102) mas inertes, o motivo é dito UMA vez em texto abaixo deles, erunneré o pré-selecionado. Uma escolha humana feita antes de a resposta chegar, num modo que ela torna inexecutável, cai pararunner— a mesma regra que já derrubavamountedquando a base some; - não sei (carregando, consulta que falha, campo ausente): nem "tem" nem
"não tem". Não pré-seleciona
mounted— a revisão da RN-513 —, e também não trava cards nem afirma em texto uma ausência que ninguém confirmou: ficacontainerselecionado, como antes.
3. A /containers recusa a subida antes do clique, com motivo próprio
decidirSubida ganha o motivo sem_broker_na_instalacao, para container e
mounted quando brokerConfigurado !== true — "não sei" não vira "tem". Ele
vem logo depois de ja_esta_de_pe e ANTES de sem_imagem_decidida: numa
instalação sem quem suba o container, mandar decidir a imagem seria apontar a
porta errada. runner nunca cai nele. A ramificação é a mesma por DESTINO de
acaoDeSubidaDoModo (quem depende do broker é quem propõe container_start),
lida do outro lado por usaBroker, e não uma segunda régua.
Consequences
- Numa instalação por Release, o modo que funciona de ponta a ponta passa a
ser o sugerido, e o que não funciona passa a dizer por quê antes de alguém
escolhê-lo. O preço:
runnerexige o agente local de pé e o Docker da máquina do usuário — o que a instalação por one-liner já entrega (ADR 0155). - No compose de DESENVOLVIMENTO o broker sobe por padrão (RN-512),
mas
BROKER_URLcontinua vazia até alguém a pôr no.env(docker/docker-compose.yml,.env.example). Sem ela, o assistente de quem desenvolve passa a mostrar o aviso — e está CERTO: semBROKER_URL, a api nunca chama o broker que está de pé, econtainer_startfalharia igual. - A RN-512 NÃO muda: o broker segue sob
profiles: ["container-broker"]no compose de produção, fora do compose de instalação, e nenhuma das cinco camadas de contenção é tocada. O que muda é a TELA parar de supor o contrário.
Fora de escopo, declarado:
- a metade do instalador (seção acima) — depende de publicar a imagem;
- a conversão de modo (
ExecutionModeSection, ADR 0111) continua podendo converter paracontainer/mountednuma instalação sem broker; ela lê a mesma rota e o campo está à mão, mas é outra tela, com outra régua de oferta (RN-559); - parar e remover (
container_stop/container_remove) não ganharam a recusa: sem broker não há container decontainer/mountedregistrado como de pé para parar, e o caso não foi medido; - o Infra Lead não sabe de broker ausente — ele recusa por MODO (RN-566), e enriquecer o contexto dele com a instalação é a frente mais cara que a RN-566 já declara;
- a sugestão de paralelização que ignora agente bloqueado por container;
- a frase de fechamento do
install.shdiz que sem broker "projeto em modo Pasta montada não sobe container" e omite o modocontainer, que também não sobe — adjacência medida e não corrigida aqui, porque o instalador é de outra frente em paralelo.