fix(link-previews): proxy sent preview media - #5627
Conversation
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
wesbillman
left a comment
There was a problem hiding this comment.
Reviewed on Wes’s behalf at exact head 48eccf547e2358f9f97b4b4e7453bb2af0b86dbf. No actionable findings from my pass. The render-boundary rewrite is correctly shared by Compact and Rich cards, preserves the original imageDomain, leaves data/external URLs unchanged, and subscribes to proxy-port publication so initial buzz-media:// fallbacks are replaced without requiring unrelated state changes. Snapshot parsing already restricts authored media to exact active-relay /media/<sha>.<image-ext> URLs tied to message content, so this does not widen the proxy trust boundary. I also traced cache reset/community-switch behavior: the existing generation guard prevents stale origin/port publication, and useMediaProxyPort rerenders on both cleared and newly resolved ports. The new E2E exercises send → uploaded snapshot → recipient parse → Compact render, delayed proxy readiness, decoded image content, and Rich rerender. git diff --check origin/main...48eccf547e2358f9f97b4b4e7453bb2af0b86dbf passes; current GitHub CI is fully green and the head is mergeable. Per policy, this is findings-only, not an approval.
wesbillman
left a comment
There was a problem hiding this comment.
Adversarial review at exact head 48eccf547e2358f9f97b4b4e7453bb2af0b86dbf: no actionable findings.
I traced the complete path rather than only the new E2E:
- Recipient-side external cards come exclusively from validated sender snapshot tags (
parseLinkPreviewSnapshots), whose media pairs are constrained to the active relay origin and matching 64-hex path/hash. This means the new render-boundary rewrite receives the relay-owned URLs it is intended to proxy, not arbitrary external image URLs. LinkPreviewAttachmentrewrites both favicon and image before the Compact/Rich fork, so every sent-card shape receives the same treatment while the originalimageDomainremains intact for display/alt metadata.- The
useMediaProxyPortsubscription closes the cold-start race: initial rendering may use thebuzz-media://fallback, and the component rerenders whenfetchProxyPortpublishes a nonzero port. Existing cache-generation guards prevent a lookup from a previous community from repopulating the cache after reset. rewriteRelayUrlstill passes external Blossom media through once the relay origin is known, and snapshot parsing independently rejects non-relay media for this path.- The E2E exercises the actual compose → upload → signed snapshot → recipient parse → Compact render flow, then releases proxy readiness and verifies both URL transition and decoded image content before switching to Rich and checking both media elements again.
I also checked failure-state behavior: the child components key image failures by the current rewritten URL, so an initial fallback/proxy failure does not permanently poison a later URL transition.
git diff --check origin/main...HEAD passes on a clean detached worktree. GitHub reports the exact head mergeable with all applicable checks terminal and green. I did not duplicate CI-equivalent suites locally.
Ready-for-review prep for the model-capabilities manifest PR: - Merge origin/main (15 commits) into the branch. The one changed-in-both file, UserProfilePopover.tsx, auto-merged cleanly: main's #5574 extracted interaction handlers into useProfileInteractionActions (disjoint region), leaving the managedAgent.model label render path untouched, so the resolveModelLabel rewire survives with identical semantics. - Re-point scripts/normative-corpus.json:562 _note from the deleted DATABRICKS_V2_OPENAI_CODE_NAMES constant to the manifest mechanism that now owns the behavior (boundary-aligned family_tokens + databricks_v2 concrete-unknown fallback). Doc-only; every expect block byte-identical. * origin/main: fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Refine channel settings and profile panels (#5574) fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659) feat(acp): deliver channel description in prompt [Context] (#4552) fix(desktop): launch Databricks OAuth from passive model discovery (#5607) chore(release): release Buzz Desktop version 0.5.10 (#5613) fix(desktop): remove 0.5.9+ perf regressions, speed up get_channels (#5599) perf(desktop): coalesce read state localStorage persistence (#5591) fix(relay): stop panicking the ingest worker on reactions to project events (#5294) fix(desktop): bound initial timeline retention (#5603) fix(relay): log event kind on the HTTP bridge /events line (#5291) feat(tracing): add PostgreSQL tracing spans (#3678) Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…igration * origin/main: fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Refine channel settings and profile panels (#5574) fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659) feat(acp): deliver channel description in prompt [Context] (#4552) fix(desktop): launch Databricks OAuth from passive model discovery (#5607) Co-authored-by: coder 0 <d97ebdbb198c7237c94f84ea8bb8a73583ea067407eebd0062abbb3962527fb1@buzz.block.builderlab.xyz> Signed-off-by: coder 0 <d97ebdbb198c7237c94f84ea8bb8a73583ea067407eebd0062abbb3962527fb1@buzz.block.builderlab.xyz> # Conflicts: # crates/buzz-media/src/lib.rs # crates/buzz-media/src/storage.rs
…graphy-staging * origin/main: Harden shared agent instruction review (#4220) chore(release): release Buzz Desktop version 0.5.11 (#5714) feat(acp): report standard adapter usage (#4950) fix(mobile): settle hydrated threads on latest reply (#4702) perf(desktop): persist channel snapshot hash (#5684) fix(agent): raise output limit and allow 3 recoveries (#5475) fix(desktop): defer foreground resume work (#5696) perf(desktop): coalesce thread-activity localStorage writes (#5693) Batch observer-store publications per relay envelope (#5680) feat(buzz-acp): idle re-sleep for woken lazy pools (#5682) fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Refine channel settings and profile panels (#5574) fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659) feat(acp): deliver channel description in prompt [Context] (#4552) fix(desktop): launch Databricks OAuth from passive model discovery (#5607) Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
…ent-config * origin/main: (31 commits) Harden shared agent instruction review (#4220) chore(release): release Buzz Desktop version 0.5.11 (#5714) feat(acp): report standard adapter usage (#4950) fix(mobile): settle hydrated threads on latest reply (#4702) perf(desktop): persist channel snapshot hash (#5684) fix(agent): raise output limit and allow 3 recoveries (#5475) fix(desktop): defer foreground resume work (#5696) perf(desktop): coalesce thread-activity localStorage writes (#5693) Batch observer-store publications per relay envelope (#5680) feat(buzz-acp): idle re-sleep for woken lazy pools (#5682) fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Refine channel settings and profile panels (#5574) fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659) feat(acp): deliver channel description in prompt [Context] (#4552) fix(desktop): launch Databricks OAuth from passive model discovery (#5607) chore(release): release Buzz Desktop version 0.5.10 (#5613) fix(desktop): remove 0.5.9+ perf regressions, speed up get_channels (#5599) ... Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> # Conflicts: # desktop/src-tauri/src/commands/personas/inbound.rs # desktop/src-tauri/src/commands/personas/inbound/inbound_tests.rs
* origin/main: Harden shared agent instruction review (#4220) chore(release): release Buzz Desktop version 0.5.11 (#5714) feat(acp): report standard adapter usage (#4950) fix(mobile): settle hydrated threads on latest reply (#4702) perf(desktop): persist channel snapshot hash (#5684) fix(agent): raise output limit and allow 3 recoveries (#5475) fix(desktop): defer foreground resume work (#5696) perf(desktop): coalesce thread-activity localStorage writes (#5693) Batch observer-store publications per relay envelope (#5680) feat(buzz-acp): idle re-sleep for woken lazy pools (#5682) fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…read-context * origin/main: (38 commits) Add mobile community invites (#5641) Harden shared agent instruction review (#4220) chore(release): release Buzz Desktop version 0.5.11 (#5714) feat(acp): report standard adapter usage (#4950) fix(mobile): settle hydrated threads on latest reply (#4702) perf(desktop): persist channel snapshot hash (#5684) fix(agent): raise output limit and allow 3 recoveries (#5475) fix(desktop): defer foreground resume work (#5696) perf(desktop): coalesce thread-activity localStorage writes (#5693) Batch observer-store publications per relay envelope (#5680) feat(buzz-acp): idle re-sleep for woken lazy pools (#5682) fix(desktop): preserve agent mention separator after send (#5623) fix(link-previews): proxy sent preview media (#5627) feat(deletion): add durable whole-community deletion (#4425) fix(desktop): preserve live channel timelines (#5662) Refine channel settings and profile panels (#5574) fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659) feat(acp): deliver channel description in prompt [Context] (#4552) fix(desktop): launch Databricks OAuth from passive model discovery (#5607) chore(release): release Buzz Desktop version 0.5.10 (#5613) ... Signed-off-by: Lazy Joe <dbd8c9941ba6dafebcef0abc015b65e75d52e7452f2ce483c9c3fd4d180f2504@buzz.block.builderlab.xyz>
The compact-preview geometry smoke test from #5629 stubs its image at the raw relay origin (http://localhost:3000/media/*.png), but #5627 rewrites sent snapshot media through the authenticated local media proxy (http://127.0.0.1:54321 in the E2E mock bridge). The two changes raced: each was green on its own branch, but once both were on main the image request goes to the proxy origin, the stub never matches, naturalWidth stays 0, and Desktop Smoke E2E (3) fails on every main and PR build. Point the route stub at the mock proxy origin, matching the existing 'sent link preview media uses the authenticated proxy' test. Co-authored-by: Thomas Petersen <thomasp@squareup.com> Signed-off-by: Thomas Petersen <thomasp@squareup.com>
…oxy (#5799) **Category:** fix (CI) **User Impact:** None — test-only change that unblocks `main` and every open PR. **Problem:** `main` has been red since #5629 landed on `45f4b91a3`: `Desktop Smoke E2E (3)` fails `compact link preview image geometry truncates long titles to one line` on every build (main run 31727837133, and e.g. #5792, #5790). Two independently-green PRs raced: #5629 added the test stubbing its preview image at the raw relay origin (`http://localhost:3000/media/*.png`), while #5627 rewrites sent snapshot media through the authenticated local media proxy (`http://127.0.0.1:54321` in the E2E mock bridge). Merged together, the image request goes to the proxy origin, the stub never matches, and `naturalWidth` stays `0`. **Solution:** Point the route stub at the mock proxy origin, matching the existing `sent link preview media uses the authenticated proxy in compact and rich cards` test in the same spec. **Testing:** Reproduced the failure locally on `45f4b91a3`, then with this fix: targeted test passes, and the full `messaging.spec.ts` smoke suite passes 58/58. Signed-off-by: Thomas Petersen <thomasp@squareup.com> Co-authored-by: Wintermute <3f1797424fd9ad6653a83665c660517777cd7f8c228c0d5907f49e01537f3ca5@buzz.block.builderlab.xyz>
Overview
Category: fix
User Impact: Sent link previews now reliably display their thumbnail and favicon when the media is hosted on the relay.
Problem: Sent preview cards loaded relay-hosted snapshot media directly, so authenticated relay requests could fail even though the snapshot itself was valid. Solution: Rewrite snapshot media at the shared card render boundary through Buzz's authenticated local media proxy, preserving the original display domain and rerendering when the proxy becomes ready.
Changes
File changes
desktop/src/shared/ui/link-preview-attachment.tsx
Routes sent preview thumbnails and favicons through authenticated relay media handling above the Compact/Rich fork while preserving original metadata.
desktop/src/testing/e2eBridge.ts
Adds an opt-in proxy-readiness seam that deterministically re-arms the production media lookup when released.
desktop/tests/e2e/messaging.spec.ts
Covers the real send, snapshot, recipient, and card-render path for Compact and Rich previews, including fallback URLs, proxied URLs, and decoded image content.
desktop/tests/helpers/bridge.ts
Exposes the opt-in media-proxy startup state to E2E tests.
Reproduction Steps
pnpm exec playwright test tests/e2e/messaging.spec.ts --project=smoke --grep "sent link preview media uses the authenticated proxy"Before / After