Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 8 additions & 28 deletions desktop/Desktop/Sources/DesktopBackendEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,20 @@ enum DesktopBackendEnvironment {
static var shouldUseDevelopmentBackends: Bool {
shouldUseDevelopmentBackends(
bundleIdentifier: AppBuild.bundleIdentifier,
updateChannel: AppBuild.currentUpdateChannel,
forceOverride: currentEnvironmentValue("OMI_FORCE_DEV_BACKENDS")
updateChannel: AppBuild.currentUpdateChannel
)
}

static func shouldUseDevelopmentBackends(
bundleIdentifier: String,
updateChannel: String,
forceOverride: String? = nil
updateChannel: String
) -> Bool {
Comment on lines 15 to 18
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Both bundleIdentifier and updateChannel are now unused parameters in shouldUseDevelopmentBackends. The call-site in the computed shouldUseDevelopmentBackends var still passes them, but the function body ignores them entirely. Swift may warn about unused variables here, and it creates a misleading API surface — callers could reasonably assume the values affect the result. Dropping them from the signature (and the call-site) makes the temporary return false state self-documenting.

Suggested change
static func shouldUseDevelopmentBackends(
bundleIdentifier: String,
updateChannel: String,
forceOverride: String? = nil
updateChannel: String
) -> Bool {
static func shouldUseDevelopmentBackends(
bundleIdentifier: String = "",
updateChannel: String = ""
) -> Bool {

// Beta channel of the production bundle routes to the dev backend
// (api.omiapi.com + dev Cloud Run desktop-backend). The dev backend is
// configured to use prod Firebase (project_id=based-hardware, prod service
// account, prod FIREBASE_API_KEY), so custom tokens it mints resolve to the
// same UID a user has on prod — and reads/writes hit prod Firestore. Same
// pattern as mobile TestFlight → staging.
//
// PR #7014 (April 2026) was reverted because at that time the dev backend
// was wired to the based-hardware-dev Firebase project, so beta users
// ended up signed in as fresh empty UIDs. The infra has since been moved
// onto prod Firebase. Verify before any future revert: dev backend
// /v1/auth/token must mint custom tokens whose UID matches prod.
if isAffirmative(forceOverride) {
return true
}

return bundleIdentifier == AppBuild.productionBundleIdentifier
&& normalizedChannel(updateChannel) == "beta"
// Beta-to-dev routing disabled: signed-in users were landing in fresh empty
// Firebase accounts (e.g. caLCFj7… instead of viUv7Gtdo… for kodjima33),
// because the dev backend's auth path mints custom tokens for new UIDs
// instead of linking to the existing prod user. Keep beta on prod backends
// until the auth flow is fixed.
return false
}

static func pythonBaseURL(
Expand Down Expand Up @@ -116,10 +102,4 @@ enum DesktopBackendEnvironment {
}
return string
}

private static func isAffirmative(_ value: String?) -> Bool {
guard let value else { return false }
let normalized = value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
return normalized == "1" || normalized == "true" || normalized == "yes"
}
}
38 changes: 4 additions & 34 deletions desktop/Desktop/Tests/APIClientRoutingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,54 +154,24 @@ final class APIClientRoutingTests: XCTestCase {
XCTAssertEqual(url, "https://desktop-backend-hhibjajaja-uc.a.run.app/")
}

func testBetaProductionBundleRoutesToDevelopmentBackends() {
XCTAssertTrue(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
func testDevelopmentBackendRoutingDisabled() {
// Beta-to-dev routing disabled — see DesktopBackendEnvironment for context.
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.computer-macos",
updateChannel: "beta"
))
// "staging" is normalized to "beta" — same routing.
XCTAssertTrue(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.computer-macos",
updateChannel: "staging"
))
}

func testStableProductionBundleKeepsProductionBackends() {
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.computer-macos",
updateChannel: "stable"
))
}

func testNonProductionBundleSkipsAutomaticBetaRouting() {
// Dev bundle and named test bundles never trigger beta-to-dev routing
// automatically. They must opt in via OMI_FORCE_DEV_BACKENDS or env URLs.
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.desktop-dev",
updateChannel: "beta"
))
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.omi-beta-dev-test",
updateChannel: "beta"
))
}

func testForceOverrideEnablesDevelopmentBackendsForAnyBundle() {
XCTAssertTrue(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.desktop-dev",
updateChannel: "stable",
forceOverride: "1"
))
XCTAssertTrue(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.omi-beta-dev-test",
updateChannel: "stable",
forceOverride: "true"
))
XCTAssertFalse(DesktopBackendEnvironment.shouldUseDevelopmentBackends(
bundleIdentifier: "com.omi.computer-macos",
updateChannel: "stable",
forceOverride: "0"
))
}

func testBaseURLReadsFromPythonEnvVar() async {
Expand Down
Loading