Repository navigation
fix(navigation): show a notice for invalid deep links - #2054
Conversation
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.
Verdict: one history defect to fix before merge; the rest is optional. Reviewed at fe55989 against merge base 42c2433. The core flow holds up: an invalid link waits through loading, identity setup and community selection, clears before it opens, never fires twice, and newer navigation cancels it. Valid links keep their unavailable/denied outcomes. The FOUNDATION edits only wire the notice store to the shared ToastNotice.
Recommended before merge (per this repo's review rules these are posted as comments; humans decide):
- With Inbox turned off, the Messages fallback adds a duplicate Messages visit, so Back does nothing once (inline on
deep-links.ts). - Product call: the warning stays on screen over a valid link that opens right after (inline on
RejectedLinkNotice.tsx).
Optional: dead ingress branch, copy for unknown hosts, docs for the Messages fallback, a held parse-only link failing denied, and notice test coverage. Each is inline.
Validation gaps: this was a source review plus one targeted real-controller probe that reproduced item 1. Hosted CI is green at this head. Packaged warm/cold OS activation and the notice at narrow widths, in both themes and with enlarged text are still unverified, as the PR says.
Exit criteria: make the fallback return to a matching preceding Messages visit instead of adding a new one, and cover repeated malformed links with Inbox disabled. Decide whether a later valid link should clear the notice.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.
Re-review at 632151b: the duplicate Messages stop is fixed, but the new step-back adds two narrower history problems (inline on deep-links.ts:145). Per this repo's review rules these are posted as comments; humans decide.
Also resolved: the notice test now uses a controlled clock across replacement and expiry, and the docs cover the Inbox-off case. The product call on whether a later valid link should clear the notice is unchanged and still open.
Validation: CI is green at this head. Two targeted real-controller probes failed at this head, one per issue below; the second used the repo's deferred browser-history fixture. Native traversal was not exercised.
Exit criteria: with Inbox off, a malformed link leaves no Forward stop to the failed Inbox, and a navigation the user makes while the fallback is in flight is never undone.
1394dd5 to
0072c0a
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account, integrating Rocket (lifecycle), Mantis (correctness/concurrency), and Groot (product/accessibility).
Reviewed head 0072c0add572132b60d1d9275341ecca23bc110b against base/merge base 802bf5aaf28658aa143cc1c914ea8c4e62882d15. Two actionable findings inline: the Inbox-off repair still races catalog restoration, and warm malformed links can leave an inert Retry on an existing ingress failure. These are comments for the author and human reviewers, not a GitHub approval or changes-requested review.
The known-off path no longer adds a failed visit or queues Back, and a later valid link clears the notice. The revised warm behavior preserves ordinary page/history state. Previously settled copy/parser observations are not reopened.
Source-only: inspected the eight-file patch, supporting callers/controller/native startup paths, changed tests, public PR description (no attached images), and five commit messages. No tests, builds, app launches, or PR code were executed. A one-time hosted-check snapshot shows CI required successful; Windows native validation and the browser flake lane were skipped. Packaged warm/cold OS activation, native focus, assistive technology, visual checks across themes/widths/text sizes, performance and human acceptance remain unverified.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account, integrating Rocket (lifecycle), Mantis (correctness/concurrency), and Groot (product/accessibility).
Reviewed head d83f948be982f8485c14316d50c38f83cbf7bad4 against base 802bf5aaf28658aa143cc1c914ea8c4e62882d15, focusing on the follow-up since 0072c0add572132b60d1d9275341ecca23bc110b.
One P2 finding inline: the new synchronous Inbox subscription can consume a launch intent before configuration/contribution publication settles. The previous warm Retry defect is repaired in source, and the catalog-last Inbox-disabled case now waits correctly.
Source-only review, including the public description (no attached images) and commit messages. No tests, builds, app launches or packaged OS activation were performed. The one-time check snapshot showed Semgrep, zizmor and DCO success only; broad CI completion, native focus, rendering, performance and human acceptance are not established. Contributor test results were not independently reproduced. This is a non-blocking COMMENT review, not approval.
os links that name no buzz destination (bare buzz://, unknown hosts, missing or malformed parameters) now open the scoped inbox page and show a transient notice instead of the ingress failure card. messages stands in when inbox is turned off. a held malformed link waits for an identity and selected community and skips the account/community denied checks; valid links keep their unavailable and denied failures. repeats replace the notice. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
… off a malformed link with inbox turned off now returns to the page it interrupted rather than replacing the failed visit with messages, so repeats add no history stops. drop the unreachable held-link reset, document the inbox-off outcome and pin the notice expiry and restart with a controlled clock. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
decide before navigating: once plugin startup settles without an inbox page, a malformed link shows its notice over the current page and creates no visit, so history gains no forward stop and no queued traversal can override a newer navigation. services exposes the assembled deep-link host for the app tests. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
the deep-link binding reports each link that names a destination, and the host clears any showing rejection notice so it never sits over a link that worked. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
… app a malformed os link that arrives after the client was first ready now only shows the rejection notice, leaving the page and history unchanged. a link read before the client was first ready launched the app, so it still opens inbox with the notice, or stays on the start page when inbox is turned off. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
… link a malformed launch link now waits for the plugin catalog as well as the client, so a catalog that turns inbox off and settles last leaves the start page in place instead of opening a failed inbox visit. the deep link host exposes inbox status and changes for that wait; newer navigation still cancels it. a malformed link that replaces a valid one still offering retry now reopens the page under that failure card, as its go back does, so no retry is left without a held link to recover. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
plugin reconciliation emits while later plugins are not yet starting, and inbox activation emits before the page cache includes its pages. the deep link host read inbox status synchronously in those windows, saw it off and dropped a held launch link. its subscription now notifies once per microtask, after both producers finish; newer navigation still cancels. Co-authored-by: goose-wayne <ae6b377e5b6d090ee22558d19246413a5731628a127e25371111badfd4861535@buzz.block.builderlab.xyz> Signed-off-by: Kalvin Chau <[email protected]>
339f6a7 to
4b8a12c
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis, and Groot coverage.
No actionable findings in this follow-up. The prior Inbox startup-ordering issue is repaired in source: availability notifications now coalesce after synchronous plugin reconciliation and page publication, and disposal suppresses pending notifications. The two new mounted integration cases cover catalog-last and Inbox-activation-last ordering. Earlier warm-link recovery and Inbox-disabled behavior remain intact in the reviewed source.
Reviewed head 4b8a12c7fe09695bc98c656c9bbda54ebc4087ab against base 662e91800af8204ec0e492522b8f23ef23b19baa, including the delta from previously reviewed d83f948be982f8485c14316d50c38f83cbf7bad4, relevant callers, and the public PR description (no attached images).
Source-only: no tests, builds, or app/native workflows executed for this review. One hosted check snapshot reports required CI successful; Windows native validation and browser flake checks were skipped. Packaged OS delivery, native focus, rendered accessibility, theme/width/text-size behavior, and incremental test cost remain unverified. This COMMENT is not approval or merge authorization.
…isibility * origin/main: (23 commits) feat(profiles): show NIP-FI verified names (BUZZ-433) (#2005) feat(identity): sign in to the organization when Buzz opens (#2086) perf(identity-names): stop rerunning name policy for live member churn (#2092) fix(sidebar): keep the channel drag preview under the pointer (#2019) fix(identity): use xyz.block.buzz.desktop federated-session keychain service (#2094) perf(relay): read each channel's remote access once per accepted batch (#2091) fix(styles): keep page status :has() on each rule's subject (#2081) fix(navigation): show a notice for invalid deep links (#2054) fix(messages): preserve held readers through equal-height resizes (#1963) perf(sidebar): subscribe to selected live and list facts (#1966) feat(desktop): align the sign-in callback page with web branding (#2038) Show linked PRs in Solo headers and move idle huddles to Chat actions (#1968) feat(messages): mark edited messages with "(edited)" (#2020) feat(desktop): bundle the buzz CLI in every package (#2027) feat(plugins): open a plugin page from buzz://plugin links (#2053) feat(plugins): managed plugin sources (#2052) test(browser): prevent sampled clock pause races (#1955) test: fix month-boundary and Sonner mount races in StatusEditor and RelayStaff tests (#2064) test: stop tests leaving temp dirs and a flake-check fixture behind (#1977) fix(messages): release Virtua's held range when scrolling stops (#2032) ... # Conflicts: # src/bundled/channels/ChannelMemberAvatars.tsx
…ice (#2718) ## Summary The Builderlab console's **Open Buzz app** button (console nav and the Agents page, `squareup/ext-builderbot-ui` `navigation.ts`) links to bare `buzz://`. OS ingress counted that as malformed. In a running app it showed "This link doesn't work", and on a cold start it opened Inbox with the same notice. #2054 added that notice; before it, the link did nothing visible. Native code already brings Buzz to the front for any deep link (`src-tauri/src/deep_links.rs` `accept`). With this change, `bindDeepLinks` skips bare `buzz://` and `buzz:///` (Windows root path) when it picks the URL to act on: - No notice, no navigation, no failure. - A cold start lands on the ordinary start page. - It never displaces a real link queued in the same batch. `deepLinkStep` and `parseBuzzLink` still return null for it, so a bare `buzz://` in message content stays plain text. Every other malformed link keeps the notice. ## Not in scope These are other Builderlab links that also hit the notice: - `buzz://sign-in` (welcome dialog **Open Buzz now**) is handled by #2579. - `buzz://nostr-bind?…` (Builderlab identity page **Connect**) is the original desktop's consent flow and was never ported. The direction for that one is still open. ## Changes - `src/features/navigation/deep-links.ts`: the `OPEN_APP_LINK` guard in candidate selection. - Tests: four new `bindDeepLinks` cases: warm `buzz://`, warm `buzz:///`, cold launch, and a bare link queued after a channel link. All four fail without the guard and pass with it. Rejection tests that used `buzz://` as their malformed example now use `buzz://unknown`, in `deep-links.test.ts` and `entity-navigation.test.tsx`, so their coverage is unchanged. - `docs/deep-links.md`: lists `buzz://` as accepted and moves the malformed-link examples to `buzz://unknown`. ## Validation (at 786ecad) - `vitest run src/features/navigation src/app/entity-navigation.test.tsx`: 10 files, 323 passed. - `tsc --noEmit` is clean, and the pre-commit and pre-push hooks pass (biome, design-system, clippy). - An independent agent review found no blockers. Its one substantive suggestion was to make sure a bare link can't displace a real one queued with it. That is adopted, with a test. **Deferred:** native OS ingress hasn't been exercised. That needs a debug bundle (`just desktop-bundle --launch`), which would take over the `buzz://` handler from the installed app. To test: with the bundle running, `open "buzz://"` should bring it forward with no notice. Quit the app and run `open "buzz://"` again: it should launch to the start page with no notice. `open "buzz://unknown"` should still show the notice. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Stuart Douglas <[email protected]> Signed-off-by: Matt Toohey <[email protected]> Signed-off-by: mtoohey <[email protected]> Co-authored-by: Vimes <d26902ac60a55be3ce7c6bb44cf3b0a0a09cf3b89067f6d9cc6e2e5015bd59a3@remote-agent-pilot.communities.buzz.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]> Co-authored-by: mtoohey <[email protected]>
Summary
An OS-delivered
buzz://link that names no Buzz destination now shows a transient "This link doesn’t work" notice instead of a failure card. This covers barebuzz://, unknown hosts, missing or malformed parameters, bad percent-encoding, malformed join links and oversize links.deep-links.tsclassifies an incoming link as invalid when it is neither an invite nor a parseable Buzz link. Invalid links bind to no account or community, so they skip the viewer/communitydeniedchecks.unavailablewith Retry,denied, loading and offline. A malformed link that replaces a valid one still showing its Retry card reopens the page under the card, as the card's Go back does, so no Retry is left with nothing to recover.createRejectedLinksholds the latest rejection;RejectedLinkNoticerenders it with the sharedToastNotice, so a repeat replaces the notice rather than stacking, and the next link that names a destination clears it.App.tsxandservices.ts(FOUNDATION) gain only the wiring for the notice and the Inbox availability status, as requested for this behavior.buzz:hrefs that parse, so invalid ones stay plain text.docs/deep-links.mddescribes the new outcome.Testing
vitest runatd83f948be(TZ=UTC): 14355 tests pass.src/features/navigationandsrc/appalone: 798. Coverage includes:buzz://, staying in place with the notice, then a valid link that clears it;buzz://, leaving the notice and no Try again.tsc --noEmitandbiome checkpass.No browser journeys added or removed.
Deferred: packaged warm/cold OS activation and native focus, and notice rendering at narrow widths, in both themes and with enlarged text.