Repository navigation
feat(browser): show a refused Builderlab app as a page in the panel - #2680
Conversation
When the native viewer exchange refuses the account (403), the app panel shows "You can't open this app" with Try again in the website's place, instead of a line of red text in the error bar. It gives no reason for the refusal. Native attach now rejects with a message and an optional page name; other failures keep the error bar. Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Nathan Thillairajah <[email protected]>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One keyboard-focus regression reproduced in Chromium and WebKit: retrying a refused app removes the focused recovery control.
| attachFailed = false; | ||
| attachStarted = false; | ||
| setLocalError(null); | ||
| setPage(null); |
There was a problem hiding this comment.
🤖 [P2] Preserve focus during refused-app retry
Focus Try again and press Enter: clearing page unmounts the focused button. In both Chromium and WebKit, document.activeElement becomes BODY while attachment is pending and remains BODY after another refusal restores the button; immediate repeated refusal also loses focus. This conflicts with the focused-retry-control requirement in src/shared/design-system/DESIGN.md:356. Keep the recovery control mounted during retry with repeat activation guarded, or provide intentional focus handoff/restoration that respects subsequent user focus. Extend BrowserHostView.test.tsx's refusal/retry test with a deferred attachment and focus assertions after repeated refusal.
There was a problem hiding this comment.
🤖 Good catch, fixed in cf3f753. Try again no longer clears the page. The page stays mounted while the retry runs, with the button in the shared Button's loading state, which keeps it focusable (focusableWhenDisabled) and ignores repeat presses. The page only clears once the website attaches. A repeated refusal just turns off loading, so focus stays on the same button.
The new test in BrowserHostView.test.tsx uses a deferred attachment and checks focus while the retry is pending, that a repeat press does nothing, and focus after a refusal, after an immediate second refusal, and through to success. It fails on the old view code (focus goes to BODY). #2681's "couldn't load" Try again had the same unmount. It picks this fix up through a merge, plus its own loading state and test in 695ee3c.
Retrying from the "You can't open this app" page cleared the page, which unmounted the focused button and dropped focus to the document body. The page now stays while the retry runs, with Try again in its loading state (still focusable, repeat presses ignored), and clears only once the website attaches. Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Nathan Thillairajah <[email protected]>
…retries The "Buzz couldn't load this app" page now stays mounted during a retry (from #2680's fix), so its focused Try again keeps focus. Put that button in its loading state too, so the retry shows as pending and repeat presses are ignored, as on the refused-app page. Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Nathan Thillairajah <[email protected]>
…urns 401 (#2678) When Buzz opens a Builderlab app in its side panel, it exchanges your organization sign-in for a viewer cookie. If that exchange comes back 401, the panel asks you to sign in again, but Settings → Identity still says you're signed in. The two disagree until something else notices. Now a 401 from the exchange triggers one background check with the sign-in adapter, using the existing `FederatedIdentity::recheck` that agent decisions and community API calls already use. If the adapter says the session ended, it moves to "reauthentication required" and Settings follows. If the session is still good, nothing changes, so a stray 401 can't sign anyone out. Other failures (403, 5xx, network) and dev broker sessions don't trigger the check, and the panel's error text is unchanged. ## Testing Unit tests cover both outcomes of the 401 check and the cases that skip it. Manually tested on macOS by nthillairajah in a local dev build that combined this PR with #2680 and #2681. The build also had a local-only switch, not part of any PR, that fakes the exchange's answer. With a faked 401, the panel showed the sign-in-again message and Settings still showed the organization sign-in as active. A normal app link loaded fine. We couldn't fake Builderlab actually revoking a session, so the "session really ended" path is only covered by the unit tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Nathan Thillairajah <[email protected]> Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
…page * origin/main: (49 commits) fix(browser): recheck the FI session when the app viewer exchange returns 401 (#2678) fix(members): find verified people who have no profile (#2554) fix(dev): clear React's dev render measures so long sessions do not grow (#2495) Move app navigation to a dock and unify conversation headers (#2626) perf(mentions): rank only the shown rows and skip empty-query Space work (#2298) fix(messages): stop bare links at fullwidth and CJK punctuation (#2404) fix(agents): treat what an agent reads as information, and give answering rules only to mentions (#2456) feat: add up arrow message editing preference (#2659) fix(channels): move focus to channel settings opened from the header menu (#2526) fix(window): restore position before size and never fall back to a sub-minimum window (#2405) fix(messages): pick the latest message with the shared ordering (#2403) fix(channels): let shift+escape through the channel settings panel (#2402) fix(builderlab): clarify signed-out agent settings (#2602) feat(builderlab): preselect the catalog's recommended model (#2552) feat(host-process): set BUZZ_VERSION for every spawned process (#2674) fix(agents): finish Delete for a synced agent with no config (#2692) ci(flake-check): select related tests within a 9-minute lane budget (#2607) feat(macos): show the closed window again when Buzz becomes active (#2658) fix(channels): show channel actions as soon as the menu opens (#2657) fix(huddles): confirm before starting a huddle from the header (#2687) ... Signed-off-by: Nathan Thillairajah <[email protected]> # Conflicts: # docs/browser.md # src-tauri/src/browser/builderlab.rs
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 The retry-focus regression is fixed and verified in Chromium and WebKit. One nonblocking P3 remains: a retry ending in a generic error drops focus when the recovery button disappears. CI is still pending; this approval does not attest to a completed CI run.
If Try again on the "You can't open this app" page ends in an error that has no page of its own, the page and its focused button go away and the error bar shows. Hand focus to that message so keyboard users aren't left on the document body. Focus moves only if it was still on the page when the retry failed. Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Nathan Thillairajah <[email protected]>
|
🤖 Thanks. I fixed the P3 in 6c52d8c. If a retry from the page ends in an error that has no page of its own, focus now moves to the error message. That message is focusable through The new test in |
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Re-reviewed the focus-handoff change. Chromium and WebKit confirm generic retry failures focus the alert while preserving intentional focus movement; pending/repeated refusal and panel-close recovery also pass. No blocking findings remain. Native IPC/upstream behavior is modeled in these browser checks. Current-head CI is still pending; this approval does not attest to a completed CI run.
…able-page * origin/main: feat(browser): show a refused Builderlab app as a page in the panel (#2680) fix(profiles): cache profiles on disk and keep dm partners through eviction (#2178) feat(profiles): let each reader show verified people by username or full name (#2356) fix(media): show transparent avatars without a black background (#2477) fix(channels): keep the reader's place when Back returns to a link-opened channel (#2500) BUZZ-518: Explain required community sign-in (#2710) feat(desktop): serve credentials to agents and your CLI, with pairing (#2260) test(solo): wait for search and access before Share focus reveal (#2573) fix(relay): answer bytes a failed spool wrote; deflake the memory read (#1970) ci(release): publish a signed Intel macOS DMG (#1825) Signed-off-by: Nathan Thillairajah <[email protected]> # Conflicts: # docs/browser.md # src-tauri/src/browser/builderlab.rs # src/features/browser/BrowserHostView.test.tsx # src/features/browser/BrowserHostView.tsx # src/features/browser/platform.test.ts
…n and Open in browser (#2681) When Buzz can't reach Builderlab to open an app in the side panel (a network failure, a 5xx, or a reply it can't read), the panel shows "Builderlab sign-in request failed" in a red bar above an empty page, with no way to retry. Now those failures show a page: a cloud icon, **Buzz couldn’t load this app**, and two buttons. **Try again** retries. **Open in browser** opens the app in your default browser, where the app's own login takes over. If the browser can't be opened, the page says so. 401, 403 and 404 behave as before, and bad URLs or credentials still use the red bar. ## Testing Rust and Vitest tests cover which failures get the page, both buttons, and the case where the browser can't open. Manually tested on macOS by nthillairajah in a local dev build that combined this PR with #2678 and #2680. The build also had a local-only switch, not part of any PR, that fakes the exchange's answer. A faked network failure and a faked 503 both showed the page with no red bar. Open in browser opened the app in the default browser, and Try again failed the same way, as expected while the fake was still on. A normal app link loaded fine. We didn't test with a real network outage. After that test, a review on #2680 found that Try again lost keyboard focus while retrying. This page gets the same fix (keep the page up during the retry, with the button in its loading state). That's covered by a unit test and was rechecked by nthillairajah in a local build before main was merged in (the merge changed no code in this PR): tabbing to Try again and pressing Enter repeatedly keeps focus on it. If a retry ends in some other error instead, focus moves to the error message. A unit test covers that part, but it hasn't been checked in the app. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Nathan Thillairajah <[email protected]> Co-authored-by: Dylan G <69953f73c9f5149d56f2155107338a5435823b938a6c430c63e779f9a8a446f9@remote-agent-pilot.communities.buzz.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
If Builderlab refuses to let your account open an app (a 403 from the viewer exchange), the Buzz side panel shows a line of red text above an empty page. It looks broken rather than like an answer.
Now a 403 shows a proper page instead: a lock icon, You can’t open this app, "The link may be wrong, or the app may have been removed. Ask whoever shared it." and a Try again button. It doesn't say why access was refused. It reuses the shared
EmptyState, the same as the app's own "You don’t have access to this" page.To support this, native
browser_attachnow returns{ message, page? }instead of a plain string, and only a 403 setspage: "denied". Every other failure keeps the existing red error bar. #2681 builds on this.Testing
Rust and Vitest tests cover the status mapping, the new error shape, and the page replacing the error bar.
Manually tested on macOS by nthillairajah in a local dev build that combined this PR with #2678 and #2681. The build also had a local-only switch, not part of any PR, that fakes the exchange's answer. With a faked 403, the panel showed the "You can’t open this app" page with no red bar, and Try again showed it again. A normal app link loaded fine. We didn't test with a real app that refuses the account.
After that test, a review found that Try again lost keyboard focus while retrying. The fix (keep the page up during the retry, with the button in its loading state) is covered by a unit test and was rechecked by nthillairajah in a local build at this head: tabbing to Try again and pressing Enter repeatedly keeps focus on it. If a retry ends in some other error instead, focus moves to the error message. A unit test covers that part, but it hasn't been checked in the app.
🤖 Generated with Claude Code