fix(app): unblock Android referral signup and integration status
What changed and why
Android referral Google signup was embedded in a WebView, and integration browser launches were gated by canLaunchUrl despite missing Android browser-visibility queries. A false native launch result was then treated as success. Task connections also never became authenticated against the current token-free server DTO introduced by merged #12451: the client still required access_token.
Open affiliate signup in the system browser, share one bounded OAuth handoff across Calendar/Gmail and task integrations, and adopt the server's connected verdict without exposing tokens. Failed/malformed/hung status reads now reach a visible retry, preserve cached information, and cannot overwrite a newer post-authentication read. Task defaults change only after authorization is confirmed and the server accepts the default; a read crossing that write cannot restore the previous choice.
Related to #21378. This is an incident follow-up, not proof that the reporter's entire problem is resolved. The general “Try again” screen, app version, integration names and whether the signup URL was the affiliate site or app.omi.me remain unspecified.
Product invariants affected
none. Existing shared Omi components, localization strings and brand palette are used; no recording, retention, account or provider-token storage changes.
How it was verified
bash app/test.sh: 5,352 passed, 21 skipped on the final source; no failures.bash app/scripts/analyze_ratchet.sh: passed, without raising the baseline.- 15 focused bridge/provider/widget regressions passed, including the actual token-free DTO for all four task services, timeout/late response behavior, default read/write races, retry and OAuth return.
make mobile-verify ARGS="fast --paths app/lib/pages/referral/referral_page.dart app/lib/pages/settings/integrations_page.dart app/lib/pages/settings/task_integrations_page.dart app/lib/providers/integration_provider.dart app/lib/providers/task_integration_provider.dart": 23 passed, no failures/skips. This is a seeded loopback lane, not live provider authorization.- Live affiliate register page inspected; Google signup is present. No account was created and no customer account was mutated.
- Shared URL-launcher guidance: https://pub.dev/packages/url_launcher#checking-supported-schemes. Google embedded-WebView policy: https://developers.googleblog.com/upcoming-security-changes-to-googles-oauth-20-authorization-endpoint-in-embedded-webviews/.
Native Samsung S26 Ultra OAuth completion and an Android APK build were not run locally (no Android SDK/device was available). CI Android compile smoke and a device/provider completion remain release checks. A native launch already sent to the OS may still complete after its caller's deadline; late URL lookup cannot launch a browser.
Tests
app/test/services/integrations/integration_oauth_test.dart: real URL-launch bridge with package query returning false, launch failure, malformed URL, one deadline and ignored late results.app/test/providers/integration_status_failure_test.dart: status isolation, bounded reads, fresh post-auth ownership, preserved cached grants, token-free server DTO and default-write/read ordering.app/test/widgets/settings/android_hanging_flows_test.dart: production referral retry/Open actions, task status retry, and no default mutation before verified authorization.
Release and customer verification
This PR is not merged, not on main, and not released. After merge, ship the Android mobile release and validate the shared flow on iOS. No backend deployment is required for this PR: it uses the existing OAuth/status contracts and keeps provider secrets on the server. No release date is claimed.
Merged #14957/#15088 are on main and preserve some previous status/default behavior; they do not cover these gaps. Open #21355 addresses web Google redirect/session handling on app.omi.me, a separate surface that needs its own merge, web deployment and provider configuration checks. It is not a substitute for this Android/affiliate fix.
Keep #21378 and Featurebase open until the reporter verifies referral signup and the named integration(s) on the released build. Request the Omi version, integration names and exact screen showing “Try again” to resolve that remaining unlocalized symptom. Do not claim a complete resolution from merge/release alone.
UI evidence
Production widgets with synthetic browser/status responses and Android theme. Headless layout captures only; a few platform-default text styles display test glyphs, and these images do not prove device OAuth completion.


Failure class
Failure-Class: none
The verified instance is unsupported browser authorization and a retired wire-field requirement; it is not the registered share-sheet anchoring/platform-comment instance. The shared browser boundary and behavioral DTO/bridge tests enforce the contracts directly. No new static guard or registry transition is introduced.