SDK Version
- Affected: SwiftClient 2.11.0 (confirmed) and 2.12.0 (code-reviewed)
- File:
Sources/TelemetryDeck/Signals/Signal+Helpers.swift, lines 121-131
Summary
On macOS, the isAppStore property incorrectly returns true for all non-Debug Release builds (including Developer ID signed and unsigned local builds). This causes the TelemetryDeck.RunContext.isAppStore and legacy isAppStore signal parameters to report incorrect values for macOS apps.
Root Cause
The isAppStore computed property uses C preprocessor macros in Swift #if directives:
static var isAppStore: Bool {
#if DEBUG
return false
#elseif TARGET_OS_OSX || TARGET_OS_MACCATALYST // <-- BUG
return false
#elseif targetEnvironment(simulator)
return false
#else
return !isSimulatorOrTestFlight
#endif
}
TARGET_OS_OSX and TARGET_OS_MACCATALYST are C preprocessor macros (defined in <TargetConditionals.h>). Swift's #if directive does not recognize C macros — they are always evaluated as false. The correct Swift compilation conditions are:
os(macOS) instead of TARGET_OS_OSX
targetEnvironment(macCatalyst) instead of TARGET_OS_MACCATALYST
Because the #elseif TARGET_OS_OSX branch is silently skipped, the code falls through to #else, which returns !isSimulatorOrTestFlight.
Why isSimulatorOrTestFlight returns false on macOS dev builds
The isSimulatorOrTestFlight property (lines 107-113) checks for a sandbox receipt:
static var isSimulatorOrTestFlight: Bool {
guard !isDebug, !isSimulator else { return false }
guard let receiptURL = Bundle.main.appStoreReceiptURL else { return false }
return receiptURL.lastPathComponent == "sandboxReceipt" || receiptURL.path.contains("sandboxReceipt")
}
A macOS Release build from Xcode (not Debug, not TestFlight) has no sandbox receipt, so this returns false. Therefore isAppStore = !false = true.
Affected Configurations
| Build type |
#if DEBUG |
TARGET_OS_OSX (Swift) |
Falls to #else |
isSimulatorOrTestFlight |
isAppStore result |
Expected |
| macOS Debug |
true |
N/A (short-circuits) |
no |
N/A |
false |
false |
| macOS Release (dev/local) |
false |
false (C macro, ignored) |
yes |
false (no receipt) |
true |
false |
| macOS Release (Developer ID) |
false |
false (C macro, ignored) |
yes |
false (no receipt) |
true |
false |
| macOS Release (App Store) |
false |
false (C macro, ignored) |
yes |
false (has real receipt, not sandbox) |
true |
true |
| macOS Release (TestFlight) |
false |
false (C macro, ignored) |
yes |
true (sandbox receipt) |
false |
false |
Only the App Store and TestFlight rows produce correct results — and only by accident (the receipt-based check happens to give the right answer). Dev and Developer ID builds are wrong.
Suggested Fix
Replace C macros with Swift compilation conditions:
static var isAppStore: Bool {
#if DEBUG
return false
#elseif os(macOS) || targetEnvironment(macCatalyst)
return false
#elseif targetEnvironment(simulator)
return false
#else
return !isSimulatorOrTestFlight
#endif
}
Note: This fix makes isAppStore always return false on macOS (matching the original intent). If TelemetryDeck wants to properly detect macOS App Store builds, a separate receipt-based or provisioning-profile-based check would be needed, similar to what isSimulatorOrTestFlight does for iOS TestFlight.
Impact
Any macOS app using TelemetryDeck SwiftClient/SwiftSDK 2.x in Release configuration (non-Debug) will incorrectly report isAppStore = true in their signal parameters (TelemetryDeck.RunContext.isAppStore and legacy isAppStore). This affects dashboard filtering and segmentation for all macOS TelemetryDeck users.
Reproduction
- Create a macOS app using TelemetryDeck SwiftSDK 2.11.0 or 2.12.0
- Build with Release configuration (not Debug)
- Send any TelemetryDeck signal
- Observe
isAppStore parameter is true in the dashboard, even though the app was not distributed via the App Store
SDK Version
Sources/TelemetryDeck/Signals/Signal+Helpers.swift, lines 121-131Summary
On macOS, the
isAppStoreproperty incorrectly returnstruefor all non-Debug Release builds (including Developer ID signed and unsigned local builds). This causes theTelemetryDeck.RunContext.isAppStoreand legacyisAppStoresignal parameters to report incorrect values for macOS apps.Root Cause
The
isAppStorecomputed property uses C preprocessor macros in Swift#ifdirectives:TARGET_OS_OSXandTARGET_OS_MACCATALYSTare C preprocessor macros (defined in<TargetConditionals.h>). Swift's#ifdirective does not recognize C macros — they are always evaluated asfalse. The correct Swift compilation conditions are:os(macOS)instead ofTARGET_OS_OSXtargetEnvironment(macCatalyst)instead ofTARGET_OS_MACCATALYSTBecause the
#elseif TARGET_OS_OSXbranch is silently skipped, the code falls through to#else, which returns!isSimulatorOrTestFlight.Why
isSimulatorOrTestFlightreturnsfalseon macOS dev buildsThe
isSimulatorOrTestFlightproperty (lines 107-113) checks for a sandbox receipt:A macOS Release build from Xcode (not Debug, not TestFlight) has no sandbox receipt, so this returns
false. ThereforeisAppStore = !false = true.Affected Configurations
#if DEBUGTARGET_OS_OSX(Swift)#elseisSimulatorOrTestFlightisAppStoreresultOnly the App Store and TestFlight rows produce correct results — and only by accident (the receipt-based check happens to give the right answer). Dev and Developer ID builds are wrong.
Suggested Fix
Replace C macros with Swift compilation conditions:
Note: This fix makes
isAppStorealways returnfalseon macOS (matching the original intent). If TelemetryDeck wants to properly detect macOS App Store builds, a separate receipt-based or provisioning-profile-based check would be needed, similar to whatisSimulatorOrTestFlightdoes for iOS TestFlight.Impact
Any macOS app using TelemetryDeck SwiftClient/SwiftSDK 2.x in Release configuration (non-Debug) will incorrectly report
isAppStore = truein their signal parameters (TelemetryDeck.RunContext.isAppStoreand legacyisAppStore). This affects dashboard filtering and segmentation for all macOS TelemetryDeck users.Reproduction
isAppStoreparameter istruein the dashboard, even though the app was not distributed via the App Store