@@ -8,20 +8,34 @@ enum DesktopBackendEnvironment {
88 static var shouldUseDevelopmentBackends : Bool {
99 shouldUseDevelopmentBackends (
1010 bundleIdentifier: AppBuild . bundleIdentifier,
11- updateChannel: AppBuild . currentUpdateChannel
11+ updateChannel: AppBuild . currentUpdateChannel,
12+ forceOverride: currentEnvironmentValue ( " OMI_FORCE_DEV_BACKENDS " )
1213 )
1314 }
1415
1516 static func shouldUseDevelopmentBackends(
1617 bundleIdentifier: String ,
17- updateChannel: String
18+ updateChannel: String ,
19+ forceOverride: String ? = nil
1820 ) -> Bool {
19- // Beta-to-dev routing disabled: signed-in users were landing in fresh empty
20- // Firebase accounts (e.g. caLCFj7… instead of viUv7Gtdo… for kodjima33),
21- // because the dev backend's auth path mints custom tokens for new UIDs
22- // instead of linking to the existing prod user. Keep beta on prod backends
23- // until the auth flow is fixed.
24- return false
21+ // Beta channel of the production bundle routes to the dev backend
22+ // (api.omiapi.com + dev Cloud Run desktop-backend). The dev backend is
23+ // configured to use prod Firebase (project_id=based-hardware, prod service
24+ // account, prod FIREBASE_API_KEY), so custom tokens it mints resolve to the
25+ // same UID a user has on prod — and reads/writes hit prod Firestore. Same
26+ // pattern as mobile TestFlight → staging.
27+ //
28+ // PR #7014 (April 2026) was reverted because at that time the dev backend
29+ // was wired to the based-hardware-dev Firebase project, so beta users
30+ // ended up signed in as fresh empty UIDs. The infra has since been moved
31+ // onto prod Firebase. Verify before any future revert: dev backend
32+ // /v1/auth/token must mint custom tokens whose UID matches prod.
33+ if isAffirmative ( forceOverride) {
34+ return true
35+ }
36+
37+ return bundleIdentifier == AppBuild . productionBundleIdentifier
38+ && normalizedChannel ( updateChannel) == " beta "
2539 }
2640
2741 static func pythonBaseURL(
@@ -102,4 +116,10 @@ enum DesktopBackendEnvironment {
102116 }
103117 return string
104118 }
119+
120+ private static func isAffirmative( _ value: String ? ) -> Bool {
121+ guard let value else { return false }
122+ let normalized = value. trimmingCharacters ( in: . whitespacesAndNewlines) . lowercased ( )
123+ return normalized == " 1 " || normalized == " true " || normalized == " yes "
124+ }
105125}
0 commit comments