Containerized provider login flow #206
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#206
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
Run
claude auth login/codex loginsessions inside a container instead of on the host, using the same runner machinery as #205 but with the master credential store mounted rw (instead of a per-run copy) so completed logins land in the master store that spawns copy from (#202). OAuth URL scrape via CapturePane keeps working through the tmux pane. With this, hosts no longer need the agent CLIs installed at all — the tools image is the only CLI distribution.Acceptance criteria
CODEX_HOME/CLAUDE_CONFIG_DIRhonored for the mount source, config-dir var pinned explicitly inside the container) — the operator override works in container mode by construction (#211)Blocked by
Human Brief
Category: enhancement
Summary: Run
claude auth login/codex logininside a container via the #205 runner with the master credential store mounted rw, so hosts no longer need provider CLIs installed.The issue body's "What to build" and acceptance-criteria checklist are the authoritative spec (grilled 2026-07-22).
Why ready-for-human rather than ready-for-agent:
Implementation is mostly reuse of the #205 runner machinery (same podman spawn, master store mounted rw instead of the #202 per-run copy; OAuth URL scrape via the existing tmux CapturePane path). But every acceptance criterion is verified by completing a real provider OAuth login in a browser against a podman-spawned session — and the lab agent sandbox can run neither podman nor a browser. An AFK agent would ship this completely blind, and a wrong mount or env would only surface as a broken login for a human later. The implement-and-verify loop belongs to a human on the dev host.
Key interfaces (for whoever picks it up):
Acceptance criteria: the checklist in the issue body.
Out of scope:
Blocked by
(recorded in the issue body: #205)
Added an acceptance criterion (last checkbox): the login container must resolve the master store through lab-side resolution — mount source from the override-aware resolvers, config-dir var pinned explicitly inside the container. This makes the
CODEX_HOME/CLAUDE_CONFIG_DIRoperator override officially supported in container mode, and is the reason #211 was closed as wontfix (the remaining host-mode-login gap is declared unsupported).Agent Brief
Category: enhancement
Summary: Run provider login sessions inside a container via the #205 runner machinery, with the master credential store mounted rw, so container-mode hosts need no provider CLIs installed.
This brief supersedes the earlier Human Brief (2026-07-22): #205 has landed since, and the open design decisions were resolved in a grilling session with the maintainer on 2026-07-25. The issue body's acceptance-criteria checklist remains the authoritative contract; this brief pins the design. Human verification of the real OAuth flows happens after the PR merges — the agent ships against unit/integration tests only (see Verification).
Current behavior:
Both provider adapters spawn their login flow (
LoginStart) as a host tmux session running the CLI from the host PATH, with no extra env. The OAuth/device URL is scraped from the pane viaCapturePanepolling; claude's pasted code is delivered withSendKeys; completion is detected lab-side by pollingAuthStatusagainst the master store on the host filesystem. Container-mode hosts therefore still need every provider CLI installed just for login.Desired behavior:
When container wiring is configured, a login session's pane command becomes a
podman runinvocation (tmux stays host-side, exactly the #205 tracer-bullet split). The CLI comes from the provider's agent-tools image mount; the master credential store is bind-mounted rw so a completed login lands in the same host directory the existing completion poller and credential injector already read. URL scrape, code paste, completion detection, and idempotent re-join of a live attempt behave identically from the web UI's perspective.Design pins (grilled 2026-07-25):
LoginStartrefuse with the actionable preflight error, mirroring the run-spawn refusals. Host-mode login remains only on servers with no container config at all — never as a silent fallback.--container-image). No per-repo resolution (login is repo-less). If no global default is set, refuse with an error naming the knob. Per-attemptEnsureImageapplies, like runs.podman runpane command. The per-provider inputs (master-store dir, config-dir env var name) come from a small login-container spec the provider declares — podman knowledge stays out of the provider packages, and the adapters' login flows (scrape/paste/poll/teardown logic) remain untouched. The decorator'sStopalso runs theRemoveContainerbackstop (a login CLI may ignore SIGHUP).$CODEX_HOME/$CLAUDE_CONFIG_DIRhonored for the mount source — the #211 criterion), mounted under the container-side home with the config-dir var pinned explicitly to the mount point. HOME is a per-attempt host scratch directory bind-mounted at the container-side home (ownership just works under--userns=keep-id), with the master-store bind nested inside; teardown wipes the scratch dir. Tools image mounted with the PATH prepend as in runs. No secrets in env; TERM forwards by name.labrun-namespace). The startup orphan sweep already accounts for live login sessions by construction, so a pending login's container survives a server restart and leaked ones are reaped — no sweep changes.Key interfaces:
tmuxx.SessionRunner— the seam the decorator implements; adapters keep callingStart/Stop/CapturePane/SendKeys/IsRunningunchanged.podmanx.RunSpec/RunArgv— reuse for rendering; a login spec omits worktree/bare/runtime/agent-sock mounts entirely.Acceptance criteria: the issue body's checklist, plus:
Out of scope: