mirror of
https://github.com/block/buzz.git
synced 2026-10-30 05:51:46 +00:00
codex/buzz-270-draft-prep
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a94ebece0e |
Revert "fix(mobile): push every message in your own Solo chats (#8615)" (#8690)
Reverts [#8615](https://github.com/block/buzz/pull/8615).
Mobile push for Solo chats returns to mention-only, matching buzz-app,
which alerts on every message only in DMs. This also removes the
lease-size guards #8615 added, since they existed to fit Solo chats into
the lease.
### Validation
- Clean revert of
|
||
|
|
8161a7cad0 |
perf(mobile): derive public keys with native libsecp256k1 (#8655)
Follows #8654. Deriving an x-only public key from a secret key with `nostr.Keys(secret).public` costs about 5.6 ms in pure Dart on an iPhone SE (2nd gen, Profile). The app does it in 10 places, including relay config, the signed-event relay's `pubkey` getter, push lease checks, status updates, and the settings identity row's `build` method. This routes all of them through `derivePublicKeyHex` from #8654, which takes 16.5 µs on the same device. Behavior is unchanged for valid keys: output is the same lowercase hex. For a malformed or out-of-range key the thrown type changes from nostr's `InvalidKeyException` to `ArgumentError`; every affected site either catches all errors or rethrows its own `FormatException`/`StateError`, and nothing in `lib` or `test` matches on the old type. Sites that need a full `nostr.Keys` object (key generation, `AccountIdentityStore`) are unchanged. ### Validation - `derivePublicKeyHex` is checked against `nostr.Keys` for 64 random keys in #8654's `event_signing_test.dart`. - Full mobile analyze and test suite pass on this branch after rebasing onto main, including the package's own tests. - iPhone 12 mini, Profile build of this stack (with #8656 and #8657 on top): paired to the internal Buzz community through Desktop; relay auth, identity row, avatar, and channel/DM/inbox loading all worked under the derived key. buzz-review-completed (agent review, Codex and security review clean; device validation above; human app test not applicable under the mobile testing exception) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: george <973be878edd6d4f79692a3827f20a6f7fe0ed0362f269ff6b6ba8867033d7d8e@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bad9d26142 |
fix(mobile): push every message in your own Solo chats (#8615)
## Summary Mobile push only covered Solo chats through explicit mentions. Solo chats are private streams rather than DMs, and the push lease subscribed channel-wide only to DMs. Agent replies in your own Solo chats therefore never woke the phone. The lease now subscribes channel-wide to the viewer's own joined, unarchived Solo chats, using the same predicate as the Solo tab, including older unlabelled Solo chats listed in the encrypted Solo record. Self-authored messages stay excluded through the existing lease ignores. Muted Solo chats stay out of the lease, like muted channels, so they push only on mention. The lease waits while the Solo record loads so an unresolved record never drops legacy Solo chats. If that record fails with no cached copy, DM and mention updates proceed without the legacy chats, which the Solo tab cannot list either, and they return when it recovers. Solo chats created by someone else still push only on mention, matching how they appear in the channel list. A lease is bounded by its channel count (750), by the relay's advertised plaintext and content sizes, and by NIP-44's 65535-byte plaintext ceiling. DMs always stay, as before. Solo chats fill the remaining room most recent first, sized with the publisher's own lease encoding, the exact NIP-44 payload length and the largest endpoint the relay accepts. Sizes are computed rather than built, so a relay's advertised limits never drive an allocation. Solo chats beyond the room push only on mention instead of failing the lease update or publication, and Notifications settings says how many. A relay too small even for DMs and mentions fails push setup visibly instead of saving a lease it would reject. Publication accepts only endpoint grants in the gateway's JSON-safe alphabet, so the sizing assumption holds. Thread replies outside DMs still do not push unless they mention you. That is a separate gap. ### Related issue None found. ### Validation - Added test: the desired lease includes joined DMs and the viewer's own Solo chats, and includes legacy Solo chats from the Solo record, and excludes archived and muted Solo chats, other people's Solo chats, and unlabelled private streams. It fails without the fix. - Added test: the sync provider holds the desired lease while the Solo record loads, proceeds without legacy chats if the record fails, and adds them once it arrives. It fails if loading is treated as empty or if a failure blocks updates. - Added tests: over the channel count, and over each size limit (relay plaintext, relay content, NIP-44 plaintext), the lease keeps every DM and exactly the newest Solo chats, reports the rest as omitted, and is accepted by `publishBuzzDevPushLease` with a grant at the relay's endpoint limit, while a max-length grant that JSON would escape is rejected as not a gateway grant. A relay advertising a 2^50-byte endpoint limit is sized without allocating. Each row fails if its guard is removed. - Added test: a relay whose content or plaintext limit cannot fit even the lease without Solo chats rejects that lease at publication, and the provider fails setup instead of saving it. It fails if the guard is removed. - Added test: the NIP-44 payload length matches real encryption at every padding boundary up to 65535 bytes. - Added test: Notifications settings shows "Older Solo chats notify only on mention" with the omitted count. It fails without the row. - Mobile lint and the full mobile test suite pass. - Not exercised end to end on a device. A signed dev build was installed on a test iPhone against a personal dev relay, but the phone's dev identity owns no assistant there, so the device could not create a Solo chat without exporting its key. This will be validated in dogfood. The relay matcher already handles channel-wide `#h` leases for DMs, and Solo messages use the same kind and scoping. buzz-review-completed 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f167c4c3e1 |
fix(push): accept canonical channel UUIDs across versions (#8609)
Starter channels use UUIDv5 IDs, but mobile push accepted only UUIDv4 channel IDs, so building a subscription that included a starter channel threw locally. After #8608, no non-v4 ID reaches mobile push today: positive `#h` filters cover joined DMs only, and mutes are limited to subscribed channels. This PR is therefore a safety net for future starter-channel subscriptions, and it prepares mobile for a relay that accepts them. Mobile now accepts canonical lowercase, hyphenated UUIDs of any version in subscriptions. It recognizes both the current `uuid-v4-lowercase` relay descriptor and a future `uuid-lowercase` descriptor. Against a `uuid-v4-lowercase` relay, mobile checks positive and mute channel filters before enrollment or publication, keeps the desired filters, and rechecks relay capabilities every five minutes instead of sending a lease the relay would reject. The relay is unchanged. It keeps validating and advertising `uuid-v4-lowercase`. Installed mobile builds reject any other `h_grammar`, and they parse the descriptor before renewal, opt-out and revocation, so changing the advertisement now would leave their leases active until expiry. The relay validation and advertisement change will follow in a separate PR once those builds have drained. `docs/buzz-push.md` records this sequencing. ### Validation - Regression tests reproduced the UUIDv5 rejection in Dart before the fix. Added coverage checks positive and mute filters, persisted subscription round trips, encrypted lease content, malformed IDs, retained bounds, parsing of both descriptor grammars, and pre-publication rejection of non-v4 IDs against a `uuid-v4-lowercase` relay. - Mobile push tests on the current head: 104 passed, 4 skipped. `flutter analyze` on the push code and tests is clean. - Before the split, exercised actual mobile lease construction, NIP44 encryption and NIP42 publication against an isolated local relay. The relay half of that exercise is no longer part of this PR. - Relay source is identical to `main`, so the relay serves the same descriptor that installed builds parse today. The standing mobile test exception applies. Agent review and changed-behavior exercise are complete. buzz-review-completed --------- Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: george <973be878edd6d4f79692a3827f20a6f7fe0ed0362f269ff6b6ba8867033d7d8e@sprout-oss.stage.blox.sqprod.co> |
||
|
|
868e2f8f32 |
refactor(push): one app profile per gateway (#8206)
Buzz push currently selects an application profile, such as `dogfood`, during client registration. We want each gateway to serve one Apple app configured by the operator instead. This removes profile selection from the client, relay, and gateway, while allowing internal and public gateways to use their own Apple identities. This PR implements that model in the Buzz source and upstream deployment chart. Discovery, enrollment, grants, and leases no longer carry an application-profile selector. Each gateway has one configured Apple application and APNs transport. The protocol changes are incompatible with the old registration format, so relays advertise `buzz-push-v1` instead of `nip-pl`. Old clients do not discover the new push capability. Updated clients use separate Keychain records and register again. The [push notes](https://github.com/block/buzz/blob/push-capability-v1/docs/buzz-push.md) describe the experimental contract. Landing this PR is the first step. Publish the matching gateway image and upstream chart, then land the [shared chart update](https://github.com/squareup/cash-helm-charts/pull/5740) and [gateway deployment update](https://github.com/squareup/builderbot-platform-core-infrastructure/pull/1085). Before cutover, stop old gateway instances and check legacy registration state. Migrations refuse to proceed if old gateway installations or active relay leases remain; they do not delete that state. Physical-device verification remains necessary before production activation. ### Validation Gateway and focused Flutter push tests pass, as do the Swift package, simulator build, and native notification/enrichment tests. A local relay advertises `buzz-push-v1` without `nip-pl` or `app_profiles`. The PostgreSQL suite passed 868 tests; its two migration-test failures were corrected and pass a focused rerun together with the gateway cutover guard. Chart rendering and release-contract checks pass. Desktop JavaScript tests, desktop and web builds, native desktop compilation, mobile analysis/tests, and desktop native tests pass. The full Rust unit lane and prescribed `just test` command pass, including workspace integration tests against task-isolated local services. The production overlay now requires an explicitly supplied APNs topic, with omission and rendered-value regression coverage. The corrected Swift checksum assertion passes the complete package suite: 78 XCTest tests and 42 Swift Testing tests. No physical-device enrollment or production cutover is claimed. Local merge validation: the embedded migration test and formatting pass after reserving profile migration 0060 behind rollback migration 0059. The local pre-push Rust lane failed ACP timing/steering tests (`idle_resets_on_stdout_activity`, `keepalive_resets_idle_past_deadline`, and the failed/missing-outcome steering tests). ACP and its dependency manifests are unchanged by this branch; all four pass in an isolated single-thread rerun. The documented local-check exception skips only the Rust pre-push lane for publication; required CI remains mandatory. Mobile and desktop pre-push lanes passed. Combined migration validation: after rollback 0059 landed, the main merge preserves profile migration 0060 and both embedded migration assertions. The focused migration test and formatting pass. The next local push again failed only the unchanged ACP idle/keepalive timing tests (1053 passed, 2 failed, 3 ignored); other lanes passed. Publication uses the same documented local Rust-lane exception; required CI remains mandatory. Follow-up review fix: removed the legacy profile column from the copied-lease fixture. All four event-follow-up contract tests pass on isolated PostgreSQL databases, covering desired and migrated schemas in dual and app-only modes. Formatting passes. Publication retains the prior passing local-lane evidence and uses the authorized pre-push exception for the known unrelated ACP timing failures; required CI remains mandatory. --------- Signed-off-by: Tom Brow <tomb@block.xyz> |
||
|
|
70d2ca7760 |
fix(mobile): tolerate unrelated NIP-11 relay metadata (#8160)
Relay capability additions such as `read_state_snapshot` currently make mobile push discovery reject otherwise valid NIP-11 documents. This blocks descriptor-dependent enrollment, lease updates, and remote revocation. Read unrelated top-level metadata permissively while preserving validation of the advertised `nip-pl` extension and the complete push descriptor. Each returned descriptor value is covered by compatibility tests; missing or malformed required push fields still fail. ### Validation - [Codex code review](https://github.com/block/buzz/pull/8160#issuecomment-6049355700) and [security review](https://github.com/block/buzz/pull/8160#issuecomment-6049486587) completed without findings on the final code. - Added 24 regression cases covering read-state metadata, arbitrary future metadata, HTTP discovery, missing/malformed push fields, and invalid extension advertisements. The six compatibility/discovery cases fail on unchanged main and pass with the fix. - All 55 focused descriptor, bootstrap, capability, and revocation tests pass. Mobile formatting and analysis pass. - Full mobile gate passes: 3,063 tests passed and four skipped with a configured gateway, plus all three tests for an unconfigured gateway build and the gateway recipe checks. - [Current-head CI](https://github.com/block/buzz/actions/runs/37706738403) passes, including Flutter tests, Android debug APK compilation, the complete iOS simulator app, and the unsigned iOS release build. - Production HTTP descriptor discovery against live personal-relay metadata passes without enrollment or relay changes. - Device enrollment, delivery, notification tap, and opt-out remain to be exercised in the updated iOS candidate. No relay or device state was changed. buzz-review-completed --------- Signed-off-by: Tom Brow <tomb@block.xyz> |
||
|
|
c432a111ca |
feat(mobile): push notifications MVP (#6269)
This PR implements MVP, iOS-only,
[NIP-PL](
|