Skip to content

🤖 refactor: convert codex/governor/copilot OAuth services to Effect and adopt handlerGen for OAuth procedures - #4034

Merged
ThomasK33 merged 4 commits into
mainfrom
effect-phase6a-oauth-siblings
Sep 1, 2026
Merged

🤖 refactor: convert codex/governor/copilot OAuth services to Effect and adopt handlerGen for OAuth procedures#4034
ThomasK33 merged 4 commits into
mainfrom
effect-phase6a-oauth-siblings

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

Wave 2 / Phase 6a of the progressive Effect migration: converts the three sibling OAuth services — codexOauthService, muxGovernorOauthService, and copilotOauthService — to Effect-native internals following the muxGatewayOauthService template from #4033, and moves all 15 OAuth router procedures (gateway, copilot, governor, codex) to handlerGen.

Background

#4033 made OAuthFlowManager Effect-native (per-flow Scope) and exposed never-failing wire-shaped *Effect surfaces (waitForEffect/cancelEffect/finishEffect/shutdownAllEffect), with the gateway's desktopCallbackPipeline as the conversion template. Phase 5 recommended splitting Phase 6 into two PRs: this is PR A (the mechanical sibling batch). coderOauthService is deliberately untouched (Phase 6b, see notes below).

Implementation

House pattern throughout: Effect.gen internals, one reason-carrying tagged error per service (CodexOauthError, MuxGovernorOAuthError, CopilotOauthError), thin Effect.runPromise Promise facades so every existing test passes unchanged.

  • Shared toWireResult (oauthUtils.ts): folds a { reason: string }-typed failure channel into the wire Result<_, string>. Generic over the error type, so a tag a caller must branch on first (e.g. MuxGatewaySessionExpiredError) is rejected at compile time. The gateway's local copy is replaced with this shared helper.
  • Desktop flows (codex, governor): startDesktopFlowEffect is Effect.uninterruptible (like the gateway's — a client abort between loopback acquisition and desktopFlows.register would leak the server). The forked desktopCallbackPipeline mirrors the gateway shape; service pipelines yield the manager's *Effect surfaces directly (no runPromise round-trips inside Effect code), and registration-timeout callbacks use Effect.runFork(manager.finishEffect(...)).
  • Device flows (codex, copilot): startDeviceFlowEffect is uninterruptible (run-to-completion registration of the flow record + expiry timeout after the device-code allocation). Polling loops become forked fibers, but cancellation stays on the existing seams (AbortController for codex, flow.cancelled for copilot) — no fiber-interruption redesign. Codex's pre-Effect polling crash handler is mirrored with Effect.catchDefect at the fork site; copilot's transient-retry try/catch becomes an error-channel fold per poll iteration. The pollingStarted guard + fork sit inside one sync step so an interrupt cannot mark polling started without launching it.
  • Waits: waitForDeviceFlowEffect uses the manager-style Effect.timeout + fold instead of a hand-rolled setTimeout race (same observable behavior: timer cleared when the deferred wins, shared deferred untouched on timeout).
  • codex getValidAuthEffect: the refresh mutex is held via Effect.acquireUseRelease (release guaranteed on success/failure/interruption — the Effect equivalent of the pre-Effect await using lock).
  • Router: 15 procedures moved to handlerGen — gateway waitFor/cancel (2), copilot (3), governor (3), codex (7 incl. disconnect). Mutations that must not be stranded by client aborts are uninterruptible in the services; waits stay interruptible.

Deliberate small behavior deltas (defect paths only): rejections from setConfigValue/refreshNow facades inside pipelines stay defects (logged by the fiber runtime) rather than being folded into error strings, matching the precedent set by the gateway conversion; the pre-Effect equivalents were unhandled rejections inside void (async () => …)() IIFEs.

Notes for Phase 6b (coderOauthService)

  • ~10 desktopFlows.* call sites, including commit-path liveness checks via has(flowId) — the finish/persist sequencing there is a correctness contract (a cancelled flow must not commit a replacement login), so it needs isolated review rather than mechanical conversion.
  • Multi-step persist/commit finish calls: finish is invoked after multi-await persist sections; converting those needs the same "sync bookkeeping now, async release in background" split that beginFinish provides, with attention to which awaits sit between the liveness check and the commit.
  • getValidAuth there has an issuer-binding check and its own cache; the codex acquireUseRelease mutex pattern from this PR should transfer directly.

Validation

  • All five OAuth suites pass unchanged: gateway (4), governor (3), codex (14), copilot (26), oauthFlowManager (20); plus router.test.ts and consumers providerModelFactory.test.ts / server.test.ts / mcpOauthService.test.ts (205 tests). No test files modified.
  • make static-check green locally.

Risks

Medium-touch refactor of login flows. The wire contracts, error strings, and cancellation semantics are preserved 1:1 (each conversion mirrors the original control flow, verified against the unchanged test suites). The main residual risk is interruption semantics under client aborts, which previously ran handlers to completion: flow-starting mutations and disconnect are explicitly uninterruptible to preserve that, and waits are interruption-safe by construction of the shared deferred.


Generated with xum • Model: anthropic:claude-fable-5 • Thinking: xhigh

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

This comment has been minimized.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83338825a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/orpc/router.ts
Comment thread src/node/services/copilotOauthService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f78d9a585

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/copilotOauthService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 968d21d16a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/codexOauthService.ts
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 7bdb52dc26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

This comment has been minimized.

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