detached 64a59d7

fix: avoid oauth auto-close on non-oauth popups

Treating any state query parameter as OAuth caused generic popups to be
misclassified and closed by the OAuth safety timer.

Remove state= from OAuth request heuristics and add regression tests for
non-OAuth state URLs and real authorize URLs.
commit
64a59d7185b5e6cda14ae8d24f6b72109726c2a9
author
brice · · 2026-02-16 14:37 UTC
parent
14868d8
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +12 -1
M internal/ui/coordinator/oauth.go +0 -1
@@ -48,7 +48,6 @@ var oauthRequestPatterns = []string{
4848 "client_id=",
4949 "redirect_uri=",
5050 "scope=",
51- "state=",
5251 "nonce=",
5352 }
5453
@@ -48,7 +48,6 @@ var oauthRequestPatterns = []string{
48 "client_id=",48 "client_id=",
49 "redirect_uri=",49 "redirect_uri=",
50 "scope=",50 "scope=",
51- "state=",
52 "nonce=",51 "nonce=",
53 }52 }
54 53
M internal/ui/coordinator/oauth_test.go +12 -0
@@ -96,6 +96,18 @@ func TestHandlePopupOAuthClose_ErrorDoesNotScheduleParentRefresh(t *testing.T) {
9696 assert.Nil(t, c.popupRefresh[parentPaneID], "oauth errors should not refresh parent pane")
9797 }
9898
99+func TestIsOAuthURL_DoesNotTreatGenericStateParamAsOAuth(t *testing.T) {
100+ url := "https://github.com/apps/linear/installations/new?state=Ar4EJk1ao3eyEDgSbYOtG8Cr4"
101+
102+ assert.False(t, IsOAuthURL(url))
103+}
104+
105+func TestIsOAuthURL_DetectsOAuthAuthorizeRequest(t *testing.T) {
106+ url := "https://auth.openai.com/oauth/authorize?response_type=code&client_id=app_123&redirect_uri=http%3A%2F%2Flocalhost%3A1455%2Fauth%2Fcallback&scope=openid+profile+email+offline_access&state=abc"
107+
108+ assert.True(t, IsOAuthURL(url))
109+}
110+
99111 func waitFor(t *testing.T, timeout time.Duration, condition func() bool) {
100112 t.Helper()
101113
@@ -96,6 +96,18 @@ func TestHandlePopupOAuthClose_ErrorDoesNotScheduleParentRefresh(t *testing.T) {
96 assert.Nil(t, c.popupRefresh[parentPaneID], "oauth errors should not refresh parent pane")96 assert.Nil(t, c.popupRefresh[parentPaneID], "oauth errors should not refresh parent pane")
97 }97 }
98 98
99+func TestIsOAuthURL_DoesNotTreatGenericStateParamAsOAuth(t *testing.T) {
100+ url := "https://github.com/apps/linear/installations/new?state=Ar4EJk1ao3eyEDgSbYOtG8Cr4"
101+
102+ assert.False(t, IsOAuthURL(url))
103+}
104+
105+func TestIsOAuthURL_DetectsOAuthAuthorizeRequest(t *testing.T) {
106+ url := "https://auth.openai.com/oauth/authorize?response_type=code&client_id=app_123&redirect_uri=http%3A%2F%2Flocalhost%3A1455%2Fauth%2Fcallback&scope=openid+profile+email+offline_access&state=abc"
107+
108+ assert.True(t, IsOAuthURL(url))
109+}
110+
99 func waitFor(t *testing.T, timeout time.Duration, condition func() bool) {111 func waitFor(t *testing.T, timeout time.Duration, condition func() bool) {
100 t.Helper()112 t.Helper()
101 113

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close