ADR 0083 — The Terminal tab gets the real consumer of the lifecycle, not the terminal
Status
Accepted. Revises the "No new HTTP route" section of ADR 0081, which deliberately deferred that route until a real consumer existed. It does not revise — and cannot revise — ADR 0065 nor PHASE 25b (CLAUDE.md), which continue to declare the interactive terminal cut: this document does not raise the container's physical wall, it only reads the state recorded from outside it.
Context
This front's original plan (PROGRAM 28, Wave 5, front F2) was "interactive
terminal," assuming that by this point the per-project container would
already have a real lifecycle — real provisioning, with the agent's
worktree living inside the container. That didn't happen. Wave 4/front F1
(ADR 0081) delivered project_containers — a state TABLE
(provisioning/running/stopped/failed/removed) and two use cases that
write and read that table — but no real Docker calls: no service mounts
/var/run/docker.sock, none runs privileged, and
RegistrarTransicaoDeContainerUseCase has no caller outside its own
tests. There is no real container running to open a terminal INSIDE it.
Implementing a terminal that fakes executing commands, or that executes in the SAME container as Brabo's monorepo — the debt ADR 0055 already describes as policy, not isolation —, would invent a capability that doesn't exist. It's the same mistake ADRs 0041/0042 already refuse for an unproven LLM provider and an uncurated catalog model: a capability is only declared once it's proven.
ADR 0081 had already named this front as the missing consumer:
Nothing in Wave 4 consumes this table over HTTP yet — the interactive terminal (25b/Wave 5) is the obvious candidate, and deciding the route's shape before knowing exactly what it needs to read would be guessing a contract. — ADR 0081
Decision
The Terminal tab does not get a terminal. It gets the real consumer
ADR 0081 was waiting for: GET /projects/:projectId/container/lifecycle
(RN-267), a read-only route, role:viewer, that mirrors
ObterCicloDeVidaDoContainerUseCase without adding logic — null when the
project was never provisioned (the common case today, since nothing in
production transitions the table) or the recorded state
(status/imageVersion/resources/failureReason/statusChangedAt).
Beneath the explanatory text that already existed in CodeBottomPanel.tsx
since PHASE 26b ("the interactive terminal doesn't exist yet — PHASE 25b"),
the tab now shows this state with a Badge translated to pt-BR and the
failure reason when there is one. The fetch only happens while the Terminal
tab is open (enabled: aba === 'terminal'), with no background polling —
the same traffic discipline RN-107 already applies to the image gate.
PHASE 25b's explanatory text is neither removed nor weakened: the
lifecycle state is additional information, not a replacement for the
explanation of why the terminal itself doesn't exist. A project able to
show running doesn't mean anything is executable there — it only means
someone (today, a test or a manual call) recorded that transition in the
table.
Consequences
What comes to exist. The first HTTP exposure of the container
lifecycle, and the first product screen that reads project_containers —
before this, the table was only visible to whoever queried the database or
the tests directly.
What stays exactly as it was. The interactive terminal. PHASE 25b remains cut and declared — no line of this ADR raises an orchestrator, mounts a Docker socket, or routes a terminal command into a container. Findings Z and AD (verb allowlist doesn't converge) remain open for the same reason as ADR 0081: closing them requires the physical wall, not a screen that reads a state table.
What stays honest by construction. Since nothing in production today
transitions project_containers, the route's most common response is
null, and the tab shows this literally ("not yet provisioned") instead
of inventing a status. The day a real orchestrator exists and starts
genuinely transitioning the table, this same screen starts reflecting that
state without needing to change — it already reads what the table says,
never what we'd wish it said.
References
- ADR 0081 — the table and the two use cases this document finally exposes over HTTP.
- ADR 0065 — PHASE 25b, which remains cut; this document does not reopen it.
- RN-105, RN-107, RN-243, RN-267, RN-268.
apps/api/src/interfaces/http/containers/containers.controller.ts,apps/web/src/routes/code/CodeBottomPanel.tsx.