Skip to content

feat: forward run container ports for agent OAuth logins - #73

Merged
ilovecrayons merged 1 commit into
mainfrom
feat/oauth-port-forward
Sep 5, 2026
Merged

feat: forward run container ports for agent OAuth logins#73
ilovecrayons merged 1 commit into
mainfrom
feat/oauth-port-forward

Conversation

@ilovecrayons

Copy link
Copy Markdown
Contributor

Agents in run containers could not finish browser OAuth logins: the harness listens on a container port (Codex uses 1455) while the browser redirect lands on the user's machine.

Port forwarding

  • The SSH server accepts direct-tcpip channels targeting run:<run-id> only. The Steer capability gates the channel, the server resolves the container address itself, and arbitrary hosts stay refused; reverse forwarding remains disabled.
  • aether forward <run-id> <port> [--local <port>] pipes a loopback listener through the channel with half-close propagation.
  • The local gateway gains forward.start / forward.status / forward.stop, and the dashboard offers "Forward a port" on live runs (defaults to 1455).

Protect state, live

run.protect now publishes a run.protected event; the dashboard flips Protect/Unprotect without a reload and marks protected runs with a shield on the board card and run header. Previously only a timeline note was published and the button label went stale.

One ending action per lifecycle stage

Kill while the agent is alive, Close (dialog asks merged or abandoned) while it waits for review, Delete once it has ended. Previously a needs-attention run offered four overlapping ending buttons at once, and Kill was offered on finished runs where it only said "use Delete instead".

Verification

  • make fmt-check vet lint test test-scripts public-audit, bun run typecheck, bun run test (580 tests) all pass.
  • E2E against a live server: aether forward <run> 1455 and the dashboard Forward dialog both served HTTP 200 from a listener inside a run container; unknown-run and dead-container forwards are refused; Protect/Unprotect flips live with the shield indicator; the Close dialog recorded an abandoned outcome and removed the run from the board.

Agents in run containers could not finish browser OAuth logins: the
harness listens on a container port (Codex uses 1455) while the
browser redirect lands on the user's machine. The server now accepts
direct-tcpip channels targeting run:<run-id>, gated by the Steer
capability, resolving the container address server-side; arbitrary
hosts are refused and reverse forwarding stays disabled. The CLI
gains aether forward, the local gateway gains forward.start/status/
stop, and the dashboard offers Forward a port on live runs.

Protecting a run now publishes a run.protected event so the
dashboard flips Protect/Unprotect live and marks protected runs
with a shield on the board and run header.

Run ending actions are one per lifecycle stage: Kill while the
agent is alive, Close (asking merged or abandoned) while it waits
for review, Delete once it has ended.
@ilovecrayons
ilovecrayons merged commit ffc7686 into main Sep 5, 2026
25 of 30 checks passed
@ilovecrayons

Copy link
Copy Markdown
Contributor Author

Merged with the integration job red. Evidence it is CI-environment flake, not this change:

  • TestIntegrationEnvironmentLifecycle times out after 120s waiting for a docker build of FROM ubuntu:24.04 + apt-get install jq on the runner - the build streams progress events but exceeds the deadline (Docker Hub pull throttling / slow runner network).
  • An unmodified main rerun (33933073384, same commit that passed 90 min earlier) fails the identical test the identical way.
  • This diff touches no image-build path (git diff main..HEAD has zero contact with the build/progress code).
  • The full make test-integration suite passes locally with real Docker: every package ok, internal/server 127s.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant