Codumentor logo Codumentor

Phase 6 — BYO Subscription via Per-User HOME

Goal

Support OAuth-based subscriptions (Claude Pro/Max, ChatGPT Plus where applicable) without reimplementing each provider's auth flow. The mechanism is: allocate a per-user HOME directory, run the CLI's own login flow with that HOME, and reuse the resulting on-disk auth state on subsequent invocations.

Preconditions

Phases 1–3 shipped (Tier-1 from phase 5 is helpful but not strictly required — per-user HOMEs work equally in Tier 0).

Deliverables

  1. auth/byo_subscription.py implementing per-user HOME allocation and lookup.
  2. Storage layout: <plugin_storage>/external_agent/homes/<user_id>/<backend>/.
  3. A login-proxy mechanism that lets a user run the CLI's interactive login with the per-user HOME applied. The exact UX of this is left to you — see Implementation steps 3 below for the two viable options.
  4. Settings UI surface: "Connect account" button per backend that supports this mode. Shows connected/disconnected state.
  5. New mode: byo_subscription value for the per-backend config (already named in §4.6 of the index).
  6. Credential resolution priority extended: per-user subscription HOME (if backend mode is byo_subscription) → per-user BYO key (mode byo_key) → technical-user (mode technical_user) → error.
  7. Tests for HOME allocation and injection; a manual smoke procedure documented in the handoff for the actual login flow (not automatable in CI without real browser-based provider auth).

New files

src/codumentor/plugins/external_agent/auth/byo_subscription.py
tests/test_external_agent_auth_byo_subscription.py

Touched:

Implementation steps

  1. Per-user HOME allocation: byo_subscription.get_home(user_id, backend) -> Path returns and lazily creates <plugin_storage>/external_agent/homes/<user_id>/<backend>/. Permissions: 0o700, owned by the Codumentor process user. Add a .gitignore if the storage dir is git-tracked anywhere.
  1. Injection at call time: when a backend's mode is byo_subscription, pass home=<that path> to adapter.build_env. Adapters already accept a home argument per §4.1 of the index; ensure they set HOME and any other env vars the CLI looks at (e.g., XDG_CONFIG_HOME) to that path.
  1. Login-proxy UX — pick one and document:

Option A — Guided manual setup (recommended for first cut). The Connect button shows the user a one-line shell command to run on the same machine as Codumentor:
``
HOME=<plugin_storage>/external_agent/homes/<user_id>/<backend> claude /login
`
The user runs it, completes the browser-based login, and clicks "I've finished." Codumentor then runs an
auth/probe` to confirm the HOME now contains a valid session. Simple, no terminal-proxy code, ships fast.

Option B — In-app terminal. A WebSocket-backed PTY that runs the login command inside the proxied HOME and streams the interactive output into a terminal widget in the UI. More polished UX, but substantial implementation work and a new attack surface. Defer unless option A is unacceptable for the deployment context.

Default to A. If you choose B, surface to the orchestrator first.

  1. Resolution priority in the credential resolution path: check the configured backend mode first. If byo_subscription, set creds = None (no api_key) and pass home. If the on-disk HOME is empty / unconfigured, return a structured error (auth/probe returns authenticated: false).
  1. Settings UI: per-backend row gains: - "Account connected" (or "Not connected") status, computed from a backend probe with the per-user HOME applied. - "Connect" button → opens a dialog with the command (option A) or terminal (option B). - "Disconnect" button → deletes the per-user HOME directory.
  1. Tests: cover HOME allocation, env injection (assert the spawned subprocess sees the correct HOME), and the resolution priority chain. The actual login is not testable in CI; document a manual smoke procedure.

Acceptance criteria

Out of scope

Handoff

Fill out the template. In "Contracts established/changed":

In "Surprises": call out any CLI that did not behave as expected when HOME was overridden (some CLIs hard-code paths under ~).