Push notifications for the bb mobile app, end to end - #1989
Draft
SawyerHood wants to merge 1 commit into
Draft
Conversation
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
from
August 20, 2026 01:07
ba231a7 to
f053391
Compare
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
from
August 20, 2026 01:29
f053391 to
516683f
Compare
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
2 times, most recently
from
August 20, 2026 02:47
a4aac2d to
a006cd6
Compare
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
from
August 20, 2026 02:57
a006cd6 to
8684ab2
Compare
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
2 times, most recently
from
August 20, 2026 03:13
3a1f4f1 to
706c87d
Compare
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
from
August 20, 2026 03:27
706c87d to
597f61c
Compare
SawyerHood
added a commit
that referenced
this pull request
Aug 20, 2026
Stack layer 3 of 4 for the bb mobile app (stack #1990). Prerequisites: #1986 (`@bb/client-core`) and #1987 (core prep). Next layer: #1989 (push notifications). ## What was wrong bb has no native phone client. The PWA works on a phone but is bounded by mobile-web limits (keyboard/viewport hacks, no push, no background reconnect, no secure credential storage, no camera/photo attachments, WebKit style-recalc stalls). Plan, decisions, and research: `plans/bb-mobile-expo.md`, `plans/bb-mobile-research/`; execution log with per-phase verification: `plans/bb-mobile-progress.md`. ## What changed New `apps/mobile` (`@bb/mobile`, Expo SDK 57 / React Native 0.86 / Expo Router / NativeWind v5, iOS first; ~81k lines of app code, ~20k of unit tests, 26 Maestro flows). Everything else in this PR is toolchain/docs; no server or web behavior changes. - Connectivity: server profiles in SecureStore; Direct mode (LAN / Tailscale / simulator) and bb connect (machine enrollment by QR/code → desktop-session cookie in the native jar, renewal, re-pair); per-profile SDK + realtime manager (ping/pong, watermark reconnect, AppState suspend/resume) + QueryClient with realtime invalidation; global mutation error toasts. - Screens: drawer sidebar + home thread list (organize/sort, pinned, unread glyphs, long-press actions), search, archived, compose with pickers (project, provider, model+reasoning, permission mode, service tier, environment incl. reuse/worktree/branch/path, machine), new project + project settings + machine setup, thread detail (FlashList timeline with every row kind via a renderer registry, native markdown, native diffs, ANSI, lightbox, unread divider, ToC, prompt-stack cards), prompt area (composer with mentions/typeahead/attachments/voice/drafts, send/queue/steer/stop, queued messages, pending-interaction banner incl. approvals, questions, ask-user-question and secret-request forms, context banner with git/PR/parent/children, message/thread/git action sheets, fork/handoff), workspace panel (Info, Diff, Files + previews, terminal = bundled xterm WebView with RN-owned socket + accessory bar, synced thread tabs), settings (general, appearance palettes from `theme.css`, experiments, providers, usage, machines list/detail/add, updates, plugins management + marketplaces, skills library/registry, haptics), deep links (`bb://`, universal link mapping, thread-open signal), outbound share. - Design system: generated native theme tokens (`scripts/generate-native-theme.ts` from `theme.css`, drift-tested), primitives (sheets, action sheets, toasts, etc.), Inter + Fira Code, hugeicons. - Toolchain: Metro resolves `@bb/*` from TS source (`source` condition scoped to workspace packages), `pnpm patch` for `expo-modules-jsi@57.0.4` on Xcode 26.2, scoped `lightningcss` override for NativeWind v5, turbo/eslint/prettier wiring, `.github/workflows/mobile-e2e.yml` (label `mobile-e2e` / nightly; Release build + Maestro) and `mobile-runner-probe.yml`, `eas.json` profiles, docs (`docs/platform-support.md`, `docs/repository-overview.md`). - Early access: the bb-side pairing surfaces (Settings → Remote access → Add mobile device, `bb connect machine-code`) are behind the `mobileApp` experiment from #1987; the app's own Settings → Experiments screen lists that toggle too (it is shared server state). - Not in this layer: push notifications (#1989). Not yet: Android, plugin frontends (SPA-in-WebView planned), inbound share (needs a native rebuild), TestFlight (needs an EAS account). ## How you verified - `pnpm exec turbo run typecheck lint test --filter=@bb/mobile` — 794 tests / 117 files, 0 lint findings. - Every phase was built by parallel agents and independently re-verified; the full Maestro regression (26 flows) passed on the iPhone 17 Pro simulator (iOS 26.3) against the seeded harness backend (`tests/integration/mobile-e2e/backend.ts`) and the connect stub gate; results table and screenshots list in `plans/bb-mobile-progress.md`. Connect enrollment was also exercised against the real `bee.getbb.app`. - On this layer specifically (no push): `phase1-shell`, `phase4b-send`, `phase5-links` flows re-run and pass. - Known gap carried in the log: on bb connect profiles the left-edge drawer swipe can also press the home row under the touch (Direct profiles are fine). > AGENT GENERATED: by Claude Opus 5 --------- Co-authored-by: Claude <noreply@anthropic.com>
Server: a `push_subscriptions` table (migration 0104) with `@bb/db` data helpers, `@bb/domain` push types, `/api/v1/notifications/push-subscriptions` (list / upsert-by-token / delete) in the server contract and routes, and a push sender that listens to the notification hub and posts to the Expo Push API when a thread gains a pending interaction, a root thread's turn finishes and waits for input, or a run fails (2 s coalescing per thread, skipped when the thread was read or the interaction answered, stale tokens pruned after a failed delivery). `BB_PUSH_NOTIFICATIONS` / `BB_EXPO_PUSH_URL` server config (startup-only, threaded through the bb-app launcher), the `sdk.notifications.pushSubscriptions` area (plus the bb-app public SDK façade), `bb notifications push-subscriptions list|add|remove`, guide / skill / docs updates. Mobile: the Expo push client — registration sync on connect / AppState / token roll / toggle (pure policy in `src/data/notifications`, RN glue in `src/notifications`), tap routing to the owning profile's thread, foreground toast, app-icon badge, the one-time "Get notified" sheet, and the Settings → Notifications per-server rows — wired into the root layout, Settings screen, e2e reset, and the phase 5 links flow. Co-Authored-By: Claude <noreply@anthropic.com>
SawyerHood
force-pushed
the
bb-mobile-4-push
branch
from
August 20, 2026 03:43
597f61c to
b0362ef
Compare
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.
Stack layer 4 of 4 for the bb mobile app (stack #1990). Prerequisite: #1988 (the app). This layer holds most of the server changes so it can be reviewed and landed separately from the app.
What was wrong
bb has no way to notify a phone when a thread needs attention: there is no device-token storage, no sender, and no client registration. The web/PWA only has in-session signals (WebSocket changes,
GET /system/attention).What changed
Server owns the policy; no daemon change (
HOST_DAEMON_PROTOCOL_VERSIONuntouched).packages/db:push_subscriptionstable (0104_push_subscriptions, Drizzle-generated migration + snapshot) and data helpers with in-memory tests.packages/server-contract+packages/domain:GET/POST/DELETE /api/v1/notifications/push-subscriptionsschemas (strict; POST upserts by Expo token),pushNotificationData {kind, projectId, threadId}.apps/server: routes +services/notifications/push-sender.ts— sends through the Expo Push API (https://exp.host/--/api/v2/push/send, batched,DeviceNotRegisteredcleanup) on three triggers: new pending interaction, turn finished (latestAttentionAt), thread error / provider failure; coalesced per thread (2 s, strongest kind wins); skipped when any client read the thread after the trigger, the interaction resolved, the thread became active again, or was archived/deleted. Title = thread title, body = short preview. ConfigBB_PUSH_NOTIFICATIONS(default on) andBB_EXPO_PUSH_URL(test override) inpackages/config+docs/configuration.md.packages/sdk:sdk.notifications.pushSubscriptions.{list,add,remove};packages/bb-apppublic SDK gains the area;apps/cli:bb notifications push-subscriptions list|add|remove [--json]; guide template + bb-cli SKILL perdocs/cli-guide-and-skill.md.apps/mobile: push client (expo-notificationsregistration per server profile through the SDK area, re-register on token change, unregister on profile removal, per-profile toggle in Settings → Notifications, foreground toast with Open, tap routing to the thread, client-derived badge) and the restored integration points in_layout.tsx/SettingsScreen.tsx/ e2e flow. Registration stays off with a clear message until the app is built with an EAS project id.How you verified
packages/db407,apps/serverpush-sender + public notifications tests (fakeexp.host; triggers, coalescing, read-skip,DeviceNotRegisteredcleanup) + alltest/public(336), sdk 97, cli 458, config 109, domain 145, server-contract 57, templates 43, bb-app 64, mobile 822 — all pass;drizzle-kit generatereports no schema drift.pnpm exec turbo run typecheck lintfor mobile/server/db/sdk/cli/config/domain/server-contract/bb-app/templates/app/integration-tests — pass (except the pre-existingconversation-outline-parity.test.tstypecheck failure on main from Keep mid-turn user exchanges visible after a turn completes #1657).phase1-shell,phase4b-send,phase5-links(asserts the Settings push row) pass;xcrun simctl pushexercised the foreground toast, background banner + badge, and tap routing with a temporary fake EAS project id.exp.hostneeds an EAS project + APNs key + a signed build on a physical iPhone.