Skip to content

fix(settings): surface actionable OAuth failures - #3319

Open
fine405 wants to merge 3 commits into
apache:mainfrom
fine405:fix/oauth-proxy-recovery
Open

fix(settings): surface actionable OAuth failures#3319
fine405 wants to merge 3 commits into
apache:mainfrom
fine405:fix/oauth-proxy-recovery

Conversation

@fine405

@fine405 fine405 commented Aug 20, 2026

Copy link
Copy Markdown

Summary

  • Preserve Codex device-authorization transport and unsupported-region failures across Runtime Host and Desktop boundaries.
  • Show durable localized recovery guidance with a direct jump to Network Settings.
  • Use the next sign-in attempt against the real OpenAI device endpoint as the destination-correct recovery check.

Follow-up to #1301 and #1302. This does not change the proxy-routing fix from #1302.

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/runtime test — 2,967 passed, 13 skipped
  • npm --workspace @maka/runtime-host test — 1,033 passed
  • npm --workspace @maka/desktop test — 979 passed

The focused recovery-navigation E2E is included, but its local run timed out while setting up the Electron fixture before product assertions. The same local branch build/typecheck validation used the three-line fix now merged upstream as #3332.

Before: #3319 (comment)
After: #3319 (comment)

Compatibility

Runtime Host compatibility epoch 29 carries the two new closed OAuth failure codes. Epoch 28 is already used by the Fast service-tier profile change.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex assisted with analysis, implementation, tests, verification, review response, and PR preparation. The human contributor reviewed the result and authorized submission.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@fine405

fine405 commented Aug 20, 2026

Copy link
Copy Markdown
Author

Before:

Snapzy_clipboard_40EDF83A-180D-43DD-9E60-E90FC38B3226

Maka Desktop diagnostic report
Captured at: 2026-08-20T12:28:03.374Z

Error
Surface: toast
Title: 无法开始登录
Description: 鉴权失败

Environment
Maka: 0.1.11
Build: packaged
Electron: 43.2.0
Chrome: 150.0.7871.129
Node: 24.18.0
OS: darwin 25.5.0 (arm64)
Locale: zh-CN
Renderer locale: zh-CN
Renderer user agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Maka/0.1.11 Chrome/150.0.7871.129 Electron/43.2.0 Safari/537.36
Workspace: ~/Library/Application Support/Maka/workspaces/default
Main process uptime: 1746s

Recent main-process logs (3)
[2026-08-20T11:58:56.672Z] LOG [startup] app ready
[2026-08-20T11:58:59.553Z] LOG [shell-env] resolved login-shell PATH (44 entries)
[2026-08-20T11:59:00.424Z] ERROR (node:7683) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.
(Use Maka --trace-deprecation ... to show where the warning was created)

Runtime Host
Epoch: 28e7ac84-0820-4e9b-9c39-ab050b7989ae
Protocol: v0 · compatibility 25
State: ready
Process: 8763 · uptime 1743s
Runtime: Node 24.18.0 · darwin 25.5.0 (arm64)
Activity: 1 connections · 1 operations · 0 residencies
Recent Runtime Host logs (0)

@fine405

fine405 commented Aug 20, 2026

Copy link
Copy Markdown
Author

After:

export-1787235161454

Maka Desktop diagnostic report
Captured at: 2026-08-20T14:17:31.704Z

Error
Surface: toast
Title: 无法开始登录
Description: 无法连接登录服务,请在网络设置中检查代理配置,然后重试登录。

Environment
Maka: 0.1.11
Build: dev @ 272d4d6
Electron: 43.2.0
Chrome: 150.0.7871.129
Node: 24.18.0
OS: darwin 25.5.0 (arm64)
Locale: zh-CN
Renderer locale: zh-CN
Renderer user agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) MakaDev/0.1.11 Chrome/150.0.7871.129 Electron/43.2.0 Safari/537.36
Workspace: ~/Library/Application Support/Maka Dev/workspaces/default
Main process uptime: 10s

Recent main-process logs (1)
[2026-08-20T14:17:22.247Z] LOG [startup] app ready

Runtime Host
Epoch: 05f0cd78-b84c-4fe4-b629-9a918570851b
Protocol: v0 · compatibility 29
State: ready
Process: 8221 · uptime 9s
Runtime: Node 24.18.0 · darwin 25.5.0 (arm64)
Activity: 1 connections · 1 operations · 0 residencies
Recent Runtime Host logs (0)

@fine405
fine405 marked this pull request as ready for review August 20, 2026 13:14
@likun666661

Copy link
Copy Markdown
Member

Scope and recovery-path review

The direction is valuable: preserving actionable OAuth failure reasons and giving users a direct path to Network Settings fixes a real UX gap. However, I think the current PR combines two different problems and expands well beyond the minimum change needed for OAuth recovery.

1. The problem statement should be corrected

#1301 describes a configured Maka proxy being bypassed during Codex OAuth token exchange/refresh. That issue was already closed by #1302, which routed those requests through the active proxy.

This PR addresses a different problem:

When Codex device authorization fails because of network transport or an unsupported egress region, the failure is flattened into a generic authentication error, so the user receives neither an actionable explanation nor a direct recovery path.

Proxy discovery is a separate feature request:

Detect possible proxy configuration from Runtime Host environment variables or the local OS/PAC configuration.

These should be defined and evaluated independently. The “Before” evidence currently proves only that the UI displayed a generic authentication failure; it does not by itself establish that proxy discovery is required to fix the failure.

2. Occam's razor: the minimum sufficient fix is much smaller

For the OAuth recovery issue, the minimum sufficient change appears to be:

  1. Preserve bounded failure categories such as network_unavailable and unsupported_region.
  2. Show accurate, durable UI copy for those categories.
  3. Add a direct action that opens/scrolls to Network Settings.
  4. Ideally, offer an OAuth-specific connectivity check.

Automatic environment/system proxy discovery, candidate adoption, restoring proxy defaults, credential deletion, a new Host operation, and a new remote-owner grant are not necessary to solve the error-reporting/recovery-path problem. I recommend keeping the failure projection + recovery navigation in this PR and moving proxy discovery/reset into separately designed changes.

3. Side effects and gaps to resolve

The current proxy test does not verify OAuth recovery.
testProxyConnection probes https://icanhazip.com and then api.country.is, not the OpenAI OAuth endpoint. A proxy may be reachable while auth.openai.com still rejects its egress region. PAC routing can also differ by destination: the system candidate is resolved for auth.openai.com, but it is tested against another domain. The UI can therefore report “Proxy is reachable” without proving that OAuth will work. A credential-free OAuth-endpoint probe should distinguish an expected authentication rejection from unsupported_country_region_territory.

Proxy discovery exposes more than credentials.
The Host projects NO_PROXY/no_proxy into candidate.proxy.bypassList, and network-proxy.detect is added to REMOTE_OWNER_OPERATION_GRANTS. Although username/password are stripped, the bypass list may disclose internal domains, private IP patterns, and corporate network topology to a remote Client. Please either avoid transmitting environment bypass entries, restrict this discovery to the local Client boundary, or explicitly justify and test this disclosure.

Only the first parseable candidate is returned.
The fixed priority is HTTPS_PROXY → ALL_PROXY → HTTP_PROXY → system/PAC. A stale inherited environment variable can hide a valid system/PAC candidate. When that first candidate fails, the UI cannot select or retry the next candidate. If discovery remains in scope, it needs a multiple-candidate/fallback policy.

System/PAC discovery has no explicit timeout.
The Settings page automatically starts detection while the proxy is disabled, and session.resolveProxy() has no bounded timeout in this flow. PAC/WPAD problems may leave the banner in “Detecting…” indefinitely. A user-initiated action plus a bounded timeout would be safer.

Reset is a multi-step, non-atomic mutation.
The flow updates Runtime Policy and then deletes the stored credential. If policy update succeeds but credential deletion fails, the UI reports reset failure after the proxy has already been disabled, while the credential may remain stored—contradicting the confirmation text. This should be one Host-owned atomic operation, or the UI/result contract should represent partial completion honestly.

The compatibility impact is broader than the OAuth fix.
Epoch 27 → 28 makes mixed Client/Host versions reject the handshake. New closed-schema OAuth failure codes may justify an epoch bump, but bundling proxy discovery, reset UX, and a new remote grant increases the rollout and review surface unnecessarily.

Recommendation

I recommend splitting the change:

  • This PR: actionable OAuth failure projection, localized recovery copy, and navigation to Network Settings; add an OAuth-specific connectivity test.
  • Follow-up: proxy discovery, with an explicit privacy boundary, bounded timeout, multiple-candidate behavior, and destination-correct verification.
  • Separate reset change: atomic reset/credential deletion semantics.

This keeps the OAuth recovery fix focused while allowing the proxy-discovery security and product behavior to be reviewed on their own merits.

中文

范围与恢复路径审视

这个方向有价值:保留可操作的 OAuth 失败原因,并给用户一个直接进入网络设置的入口,确实补上了真实的 UX 缺口。但当前 PR 混合了两个不同的问题,而且明显超出了 OAuth 恢复所需的最小改动。

1. 建议修正问题定义

#1301 描述的是:Maka 已配置代理,但 Codex OAuth token exchange/refresh 绕过了代理。这个问题已经由 #1302 修复并关闭。

当前 PR 实际解决的是:

当 Codex device authorization 因网络传输失败或出口地区不受支持而失败时,错误被压平成通用鉴权失败,用户既得不到可操作的解释,也没有直接恢复路径。

而代理发现属于另一个独立需求:

从 Runtime Host 环境变量或本机系统/PAC 设置中发现可能的代理配置。

这两个问题应当分别定义、分别验证。目前的 Before 证据只能证明 UI 显示了通用鉴权失败,不能单独证明“自动发现代理”是修复该问题的必要条件。

2. 从奥卡姆剃刀看,最小充分修复应该小得多

对于 OAuth 恢复问题,最小充分变更应当是:

  1. 保留 network_unavailableunsupported_region 等有界失败类别。
  2. 针对这些类别显示准确、持久的提示。
  3. 提供直接打开并滚动到网络设置的操作。
  4. 最好提供一次针对 OAuth 服务的连接检查。

环境/系统代理自动发现、候选采用、恢复代理默认值、删除凭据、新增 Host operation 和 remote-owner grant,都不是解决“错误报告与恢复入口”问题的必要条件。建议本 PR 只保留失败投影与恢复导航,把代理发现和 reset 拆到独立变更中。

3. 需要处理的副作用和缺口

当前代理测试不能证明 OAuth 已恢复。
testProxyConnection 访问的是 https://icanhazip.comapi.country.is,而不是 OpenAI OAuth endpoint。代理可达不代表 auth.openai.com 接受该出口地区。PAC 还可能针对不同域名采用不同路由:系统候选是为 auth.openai.com 解析的,测试却访问另一个域名。因此 UI 可能显示“代理可达”,但 OAuth 依然失败。建议加入无凭据的 OAuth endpoint probe,用正常鉴权拒绝和 unsupported_country_region_territory 来区分结果。

代理发现暴露的不只是凭据。
Host 会把 NO_PROXY/no_proxy 投影为 candidate.proxy.bypassList,同时把 network-proxy.detect 加入 REMOTE_OWNER_OPERATION_GRANTS。虽然用户名和密码被移除了,但 bypass list 仍可能泄露内部域名、私网 IP pattern 和公司网络拓扑。建议不要跨边界传输环境 bypass entries,或者把发现限制在本地 Client,或者明确论证并测试该信息披露。

只返回第一个可解析候选。
当前优先级固定为 HTTPS_PROXY → ALL_PROXY → HTTP_PROXY → system/PAC。一个过期的继承环境变量可能遮蔽正确的系统/PAC 代理;第一个候选测试失败后,UI 也无法选择或继续尝试下一个候选。如果发现功能保留在本 PR,需要明确多候选或 fallback 策略。

系统/PAC 检测没有显式超时。
代理关闭时,设置页会自动开始检测,而 session.resolveProxy() 在这条链路中没有有界超时。PAC/WPAD 异常可能让 UI 长期停留在“正在检测”。显式由用户触发并增加超时会更稳妥。

恢复默认是非原子的多步变更。
当前流程先更新 Runtime Policy,再删除凭据。如果策略更新成功、凭据删除失败,UI 会显示恢复失败,但代理已经关闭,凭据还可能残留,这与确认文案不一致。建议做成一个 Host-owned 原子操作,或者让结果契约和 UI 能诚实表达部分成功。

兼容性影响大于 OAuth 修复本身。
epoch 27 → 28 会让新旧 Client/Host 在握手阶段拒绝互通。新的 closed-schema OAuth failure code 可能确实需要 epoch bump,但把代理发现、reset UX 和 remote grant 一起加入,会不必要地扩大发布和审查范围。

建议

建议拆分为:

  • 当前 PR: OAuth 可操作失败投影、本地化恢复文案、跳转网络设置;增加 OAuth-specific connectivity test。
  • 后续 PR: 代理发现,明确隐私边界、超时、多候选行为和目标域名正确的验证方式。
  • 独立 reset 变更: 保证恢复设置与凭据删除的原子语义。

这样既能尽快修复 OAuth 恢复体验,也能让代理发现相关的安全边界和产品行为得到独立、充分的审查。

@fine405

fine405 commented Aug 20, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed review. I agree that this PR conflated the follow-up OAuth recovery problem with proxy discovery and reset.

I have narrowed the branch locally to:

  • preserve bounded network_unavailable and unsupported_region failures through the Runtime Host and Desktop bridge;
  • show durable, localized recovery copy with a direct jump to Network Settings;
  • remove environment/system proxy discovery, candidate adoption, network-proxy.detect, the remote-owner grant, and proxy reset from this PR.

I also agree that the existing generic proxy probe cannot establish OAuth recovery. The recovery copy now tells the user to update Network Settings and retry sign-in. That retry performs the destination-correct POST /api/accounts/deviceauth/usercode request and distinguishes transport failure from unsupported_country_region_territory, without adding another diagnostic contract.

Epoch 29 remains necessary because the OAuth failure codes extend the closed projection schema; upstream already uses epoch 28.

Proxy discovery should be a separately designed change with a local/privacy boundary, bounded user-initiated detection, and ordered fallback behavior. Reset should likewise be separate and Host-owned so policy and credential changes have honest atomic semantics.

The reduced patch is 16 files / 331 additions instead of 32 files / 1,014 additions. Local lint, format, build, typecheck, Knip, Runtime (2,967 passed / 13 skipped), Runtime Host (1,033 passed), and Desktop (979 passed) are green. A focused recovery-navigation E2E was added, but its local run was blocked during Electron fixture startup before the assertion; I will not claim it as locally passing. The branch update is prepared locally and will be pushed after contributor sign-off.

Prepared and posted with OpenAI Codex at the contributor request.

@fine405 fine405 changed the title fix(settings): guide OAuth proxy recovery fix(settings): surface actionable OAuth failures Aug 20, 2026
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.

2 participants