feat(storage): productionize Azure Blob backend - #1
Merged
Conversation
Signed-off-by: Ross Hartmann <RossHartmann@users.noreply.github.com>
## Summary - Show all colon emoji autocomplete matches - Rank exact and prefix shortcodes before weaker matches - Add a regression test and screenshot ## Validation - `pnpm test` - `pnpm build` - `pnpm exec playwright test --project=smoke tests/e2e/custom-emoji.spec.ts --grep "exact standard shortcode"` - `just desktop-tauri-clippy` Native Tauri tests were attempted but could not link because the local disk filled during compilation. --------- Signed-off-by: kenny lopez <klopez4212@gmail.com>
## Summary Communities joined via an invite link never connect: the app dials `ws://` on port 80 instead of `wss://` on 443 and sits on "Reconnecting…" indefinitely. `RelayConfig.baseUrl` is documented as an HTTP origin, but the two onboarding flows disagree on what they persist: - **Device pairing** validates and stores `https://` — `pairing_provider.dart:657` throws on anything else. - **Invite join** stores the relay URL straight off the invite link, and `deep_link.dart:165` always emits `ws://` or `wss://`. `wsUrl` only special-cased `https://`, so a `wss://` base fell through to the plaintext branch: ```dart final scheme = uri.scheme == 'https' ? 'wss' : 'ws'; // 'wss' is not 'https' ``` The claim request itself succeeds, because `_claimUrlFromRelay` (`invite_join_provider.dart:242`) maps `wss → https` explicitly. Only the socket path is missing that conversion — which is why the community appears, correctly named, and then never loads. The same `baseUrl` also feeds `/query` (`relay_session.dart:136`), media upload (`media_upload.dart:765`), Blossom auth (`media_auth.dart:128`) and `relayClientProvider` (`relay_provider.dart:113`), so those requests were malformed too. Where port 80 *does* answer, it is additionally a silent TLS downgrade after `validateInviteRelayUri` insisted on `wss://`. This folds the websocket schemes back to their HTTP equivalents in `baseUrl` itself, so every consumer is correct by construction rather than needing a second getter remembered at each call site, and communities **already persisted** with `wss://` are repaired on read without a migration. `community_icon_provider.dart:46` already performs this same conversion locally. One subtlety worth flagging for review: the normalization is derived in the getter rather than applied in the constructor, so the constructor stays `const`. The compile-time fallback at `relay_provider.dart:77` relies on const canonicalization for a stable identity across rebuilds, and Riverpod's `defaultUpdateShouldNotify` is `previous != next` (`element.dart:361`), which falls back to identity for this class. A `factory` constructor here yields a fresh instance per rebuild, which tears down and resubscribes every listener — `channels_provider_test.dart` catches it as an unexpected unsubscribe during reconnect. ### Related issue Fixes block#2662. ### Testing `flutter test` — **705 passed, 1 skipped, 0 failed** `flutter analyze` — No issues found `dart format --set-exit-if-changed .` — 249 files, 0 changed Run against the Hermit-pinned SDK (Flutter 3.41.7 / Dart 3.11.5), matching CI. 10 new unit tests in `mobile/test/shared/relay/relay_config_test.dart` covering both onboarding schemes, `http`/`https` passthrough, non-default ports, and agreement between the invite and pairing paths for the same relay. Verified end-to-end against a self-hosted relay behind `tailscale serve`, which terminates TLS on 443 and leaves port 80 closed. Relay logs show the invite claim succeeding over HTTPS at the moment of joining, while no WebSocket connection ever arrives — no `WebSocket connection established`, no NIP-42 auth, no `kind:0` profile, no push registration — across the relay's entire history, even though the member row is present and correct. Port-80 refusals are not logged by `tailscaled`'s netstack, which is why the retries leave no trace server-side. Reproduced on both iOS and Android. --------- Signed-off-by: Krishna C <github@kumb.uk>
## Summary - reconcile stale native-scroll anchors when a reply arrives at the physical floor - clear the thread new-message affordance instead of incrementing it from stale cached state - preserve the existing mid-history path and add direct lifecycle regression coverage ## Why PR block#3411 fixed geometry-driven reconciliation, but the reply-arrival branch still trusted a cached `message` anchor without checking the rendered position. Native anchoring could return a short thread to the floor without another scroll/resize callback, then the next reply incremented the pill anyway. ## Verification - Desktop checks passed - Desktop typecheck passed - focused lifecycle test passed (6/6) - push hook full Desktop unit suite passed (3,770/3,770) - `git diff --check` passed Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
🤖 ## Summary - Keep the relay reconnect notification dismissed across repeated connection retries during one continuous outage. - Re-arm the notification after recovery or relay lifecycle replacement, including switches between communities that use the same relay URL. - Preserve the existing dedicated path for authentication and other application-level errors. ### How an outage is tracked The AppShell-owned relay-card hook treats an outage as one contiguous runtime episode rather than assigning it a persisted ID. A hook-local `outageActiveRef` is armed by the first qualifying unreachable/degraded observation. While it is armed, intermediate retry states (`connecting`, `reconnecting`, `stalled`, and `disconnected`) belong to that same episode, so retry churn cannot clear dismissal or emit another notification. The hook receives the same lifecycle identity used by community initialization: community ID plus `reinitKey`. This distinguishes multiple communities even when they share a relay URL, and it also changes when the active community is explicitly reinitialized. The latch and dismissal are reset when that identity changes or when the relay singleton reports its authoritative `idle` teardown state. A successful `connected` state also closes the episode and re-arms the next outage. These boundaries deliberately bias toward re-notifying rather than suppressing a later outage: recovery, community switch/reinit, or relay teardown cannot leave the hook stuck believing an old outage is still active. No outage state is persisted beyond the mounted hook lifecycle. ### Related issue None found. ### Testing - `pnpm --dir desktop typecheck` - `pnpm --dir desktop test` — 3,769 passed - `pnpm --dir desktop check` - `pnpm --dir desktop build:e2e` - `pnpm --dir desktop exec playwright test tests/e2e/sidebar-relay-card.spec.ts --project=integration` — 11 passed --------- Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
🤖 ## Summary Agent-authored mentions currently depend on matching visible `@Name` text to channel profiles. That makes notification delivery ambiguous when names collide or profiles change, and it encourages an extra post-send lookup just to confirm that the intended `p` tags were emitted. This change makes `buzz messages send` mirror Desktop's existing model: the message keeps a readable name in its content while the recipient pubkey is supplied separately. ```bash buzz messages send \ --channel <UUID> \ --content '@alice could you review this?' \ --mention <alice-hex-or-npub> ``` `--mention` is repeatable. The CLI normalizes and deduplicates explicit pubkeys, merges them with any names it can resolve from the channel, and gives explicit identities priority under the existing 50-mention limit. Before uploading attachments, signing, or publishing, the command checks every resulting pubkey against the channel's current membership: - Members are mentioned normally. - Non-members stop the send and produce an actionable error. - `--allow-non-member-mentions` deliberately sends notifying `p` tags without adding anyone to the channel. Sending a message never changes membership. On success, `mention_pubkeys` is read from the exact signed event and returned with the relay response, so callers can verify the emitted recipients without another query. Managed-agent guidance teaches this single-command mention flow. Desktop mention behavior and the Nostr event schema are unchanged. Forum guidance is intentionally handled separately in block#3596. ### Related issue None found. This replaces the earlier guidance-only approach in this PR with the underlying CLI behavior it required. ### Testing - `cargo test -p buzz-sdk` - `cargo test -p buzz-cli` - `cargo test -p buzz-acp` - `cargo test --manifest-path desktop/src-tauri/Cargo.toml` --------- Signed-off-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Signed-off-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Co-authored-by: npub1fdupjvyregj3z2tx7gx5x6py04zw89jm5usef9lyea4f3vcgh8qq9zgkdz <4b78193083ca25112966f20d4368247d44e3965ba7219497e4cf6a98b308b9c0@buzz.block.builderlab.xyz> Co-authored-by: npub13n66s06epmqf2kc3v373ez8hj65cuzyvxzjf93vwpervxqn2u7jq2qd9je <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
…#3602) ## What and why The Buzz AppImage is built on `ubuntu:22.04`, which links WebKitGTK against FreeType 2.11.1. Because `libfreetype.so.6` is on the linuxdeploy community excludelist, the bundled WebKit loads the **host's** FreeType at runtime instead of the bundled one. FreeType 2.13.0 (released 2023-02-09) added `FT_Bool read_variable` to `FT_ColorStopIterator`, growing the struct from 16 to 20 bytes. Any host running FreeType ≥ 2.13 (Fedora 42+, Ubuntu 24.04+) has a struct-layout mismatch with the 22.04-compiled WebKit. The mismatched offsets corrupt color-stop index arithmetic inside Skia's COLRv1 renderer, producing the assertion abort in issues block#2548 and block#2982: ``` stl_vector.h:1123: Assertion '__n < this->size()' failed. ... colrv1_configure_skpaint(FT_Face, ...) ... ``` ## Fix Bump the build container to `ubuntu:24.04` (noble), which ships FreeType **2.13.2**. Noble's struct layout matches every crash-affected host. The ABI mismatch disappears and the crash is eliminated at root. WebKitGTK also advances from **2.50.4** (jammy backport) to **2.52.3** (noble backport). ## Glibc floor change | Build base | glibc floor | Oldest supported AppImage distro | |---|---|---| | ubuntu:22.04 (before) | 2.35 | Ubuntu 22.04 LTS, Debian 12 | | ubuntu:24.04 (after) | 2.39 | Ubuntu 24.04 LTS, Fedora 40+ | Ubuntu 22.04 LTS and Debian 12 users lose AppImage support. Both distributions continue to receive first-class `.deb` / `.rpm` packages, which use the system WebKit and are unaffected. The crash-affected users (Fedora 42/44, Ubuntu 24.04+) all have glibc ≥ 2.39. ## Changes - `.github/workflows/linux-canary.yml:24` — container pin updated to `ubuntu:24.04@sha256:4fbb8e6a…` - `.github/workflows/release.yml:479` — same container pin updated - `.github/workflows/release.yml:501` — comment version string updated from 22.04 to 24.04 `fix-appimage.sh` and `desktop/src-tauri/**` are untouched. The block#3573 fontconfig stopgap remains active; retirement is a separate follow-on PR once this fix is verified on a shipped build. ## Sequencing `docs/linux-rendering-troubleshooting.md` (introduced in block#3573) will receive a glibc-floor callout section once block#3573 merges — adding it here would conflict with block#3573's open branch. Context: block#2548, block#2982. Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary Correlates trace + span IDs with logs, allowing traces and logs to be bridged seamlessly ### Related issue none found ### Testing Unit tests Signed-off-by: David Grochowski <dgrochowski@squareup.com> Co-authored-by: Amp <amp@ampcode.com>
…rage-adapter Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Productionizes Azure Blob Storage as a runtime-selectable Buzz backend while preserving the existing S3/MinIO path.
The production implementation plan and live-eval ledger remain in Kiingo/kiingo PR #8628. Real-Azure recovery validation and production deployment are intentionally still launch gates.
Targeted validation
Azurite passed the adapter contract and the production relay Git/CAS gate, including single-winner create-only and ETag races. Rust formatting and both Helm backend renders passed.