Manual authorization links now behave as transient recovery state: a fresh login clears older URLs, a successful copy clears the exposed URL before polling, and logged-in status defensively drops any stale manual link.
Constraint: OAuth authorization URLs should not survive beyond the active recovery action.
Rejected: Keep the copy button after a successful copy | that leaves an expired authorization URL visible after later auth state changes.
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts
Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts src/__tests__/generalSettings.test.tsx --testNamePattern "ChatGPT|OpenAI OAuth|Providers tab|ChatGPTOfficialLogin|hahaOpenAIOAuthStore"
Tested: cd desktop && bun run lint
Tested: git diff --check
When the desktop shell cannot open a browser, the ChatGPT OAuth component keeps the transient authorization URL available for copy and starts polling after that explicit fallback action.
Constraint: OAuth authorization URLs are transient UI state and must not be persisted.
Rejected: Tell users to find the URL in server logs | the desktop flow does not expose those logs as the recovery surface.
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts
Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts src/__tests__/generalSettings.test.tsx --testNamePattern "ChatGPT|OpenAI OAuth|Providers tab|ChatGPTOfficialLogin|hahaOpenAIOAuthStore"
Tested: cd desktop && bun run lint
Tested: git diff --check
The desktop app now has a dedicated OpenAI OAuth API client and store mirroring the existing Claude Official flow. The component uses the existing browser-open plus polling pattern and never exposes token material to the UI.
Constraint: OAuth status responses must not return token bodies
Rejected: Reuse Claude OAuth store | the status shape and endpoint differ
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/stores/hahaOpenAIOAuthStore.test.ts
Tested: git diff --check