@scalebun-release/react-native 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -0
  3. package/android/build.gradle +94 -0
  4. package/android/consumer-rules.pro +28 -0
  5. package/android/src/androidTest/java/com/scalebun/rn/ota/ScaleBunOtaVerifierInstrumentedTest.kt +112 -0
  6. package/android/src/main/AndroidManifest.xml +14 -0
  7. package/android/src/main/java/com/scalebun/core/crash/CrashStorage.kt +155 -0
  8. package/android/src/main/java/com/scalebun/core/crash/NativeCrashHandler.kt +93 -0
  9. package/android/src/main/java/com/scalebun/core/performance/ANRWatchdog.kt +100 -0
  10. package/android/src/main/java/com/scalebun/core/performance/AppStartCollector.kt +180 -0
  11. package/android/src/main/java/com/scalebun/core/performance/FrameMetricsCollector.kt +230 -0
  12. package/android/src/main/java/com/scalebun/core/performance/PerformanceCore.kt +165 -0
  13. package/android/src/main/java/com/scalebun/profiler/ProfilerModule.kt +398 -0
  14. package/android/src/main/java/com/scalebun/profiler/ProfilerPackage.kt +24 -0
  15. package/android/src/main/java/com/scalebun/profiler/collectors/CpuCollector.kt +161 -0
  16. package/android/src/main/java/com/scalebun/profiler/collectors/IncidentDetector.kt +223 -0
  17. package/android/src/main/java/com/scalebun/profiler/collectors/MemoryCollector.kt +157 -0
  18. package/android/src/main/java/com/scalebun/profiler/collectors/RenderCollector.kt +194 -0
  19. package/android/src/main/java/com/scalebun/profiler/collectors/SamplerScheduler.kt +218 -0
  20. package/android/src/main/java/com/scalebun/profiler/collectors/ThreadCollector.kt +142 -0
  21. package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkModule.kt +1117 -0
  22. package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkPackage.kt +24 -0
  23. package/android/src/main/java/com/scalebun/replaysdk/capture/CaptureReason.kt +47 -0
  24. package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureManager.kt +574 -0
  25. package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureScheduler.kt +187 -0
  26. package/android/src/main/java/com/scalebun/replaysdk/capture/UiStabilityDetector.kt +214 -0
  27. package/android/src/main/java/com/scalebun/replaysdk/core/ReplayConfig.kt +144 -0
  28. package/android/src/main/java/com/scalebun/replaysdk/core/ReplayLogger.kt +31 -0
  29. package/android/src/main/java/com/scalebun/replaysdk/core/SessionIdGenerator.kt +15 -0
  30. package/android/src/main/java/com/scalebun/replaysdk/models/ReplayModels.kt +94 -0
  31. package/android/src/main/java/com/scalebun/replaysdk/outbox/NativeOutbox.kt +574 -0
  32. package/android/src/main/java/com/scalebun/replaysdk/outbox/OutboxUploader.kt +559 -0
  33. package/android/src/main/java/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.kt +126 -0
  34. package/android/src/main/java/com/scalebun/replaysdk/session/SessionManager.kt +322 -0
  35. package/android/src/main/java/com/scalebun/replaysdk/storage/ReplayStorage.kt +136 -0
  36. package/android/src/main/java/com/scalebun/replaysdk/timeline/TimelineCollector.kt +28 -0
  37. package/android/src/main/java/com/scalebun/replaysdk/tracking/InteractionTracker.kt +470 -0
  38. package/android/src/main/java/com/scalebun/replaysdk/tracking/ScreenTracker.kt +20 -0
  39. package/android/src/main/java/com/scalebun/replaysdk/tracking/ScrollContextProbe.kt +188 -0
  40. package/android/src/main/java/com/scalebun/replaysdk/transport/ReplayTransport.kt +99 -0
  41. package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceRecorder.kt +121 -0
  42. package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceTranscriber.kt +170 -0
  43. package/android/src/main/java/com/scalebun/rn/ScaleBunPackage.kt +113 -0
  44. package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashModule.kt +188 -0
  45. package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashPackage.kt +22 -0
  46. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngageModule.kt +579 -0
  47. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngagePackage.kt +22 -0
  48. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunNotificationPresenter.kt +110 -0
  49. package/android/src/main/java/com/scalebun/rn/ota/BsPatch.kt +240 -0
  50. package/android/src/main/java/com/scalebun/rn/ota/BundleDownloader.kt +195 -0
  51. package/android/src/main/java/com/scalebun/rn/ota/DeviceIntegrity.kt +81 -0
  52. package/android/src/main/java/com/scalebun/rn/ota/DownloadFailure.kt +55 -0
  53. package/android/src/main/java/com/scalebun/rn/ota/OtaProtocol.kt +244 -0
  54. package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaKeyRegistry.kt +100 -0
  55. package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaModule.kt +683 -0
  56. package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaReleaseVerifier.kt +136 -0
  57. package/android/src/main/java/com/scalebun/rn/ota/SlotManager.kt +578 -0
  58. package/android/src/main/java/com/scalebun/rn/ota/TlsPinning.kt +118 -0
  59. package/android/src/main/java/com/scalebun/rn/performance/PerformanceModule.kt +217 -0
  60. package/android/src/main/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.kt +77 -0
  61. package/android/src/main/java/com/scalebun/rn/storage/ScaleBunStorageModule.kt +68 -0
  62. package/android/src/main/java/com/scalebun/storage/KvFileStore.kt +174 -0
  63. package/android/src/newarch/java/com/scalebun/profiler/ProfilerSpec.kt +12 -0
  64. package/android/src/newarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +12 -0
  65. package/android/src/newarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +15 -0
  66. package/android/src/newarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +16 -0
  67. package/android/src/newarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +12 -0
  68. package/android/src/newarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +14 -0
  69. package/android/src/newarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +16 -0
  70. package/android/src/oldarch/java/com/scalebun/profiler/ProfilerSpec.kt +34 -0
  71. package/android/src/oldarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +77 -0
  72. package/android/src/oldarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +40 -0
  73. package/android/src/oldarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +42 -0
  74. package/android/src/oldarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +27 -0
  75. package/android/src/oldarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +18 -0
  76. package/android/src/oldarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +26 -0
  77. package/bin/lib/androidCodemod.js +370 -0
  78. package/bin/lib/iosCodemod.js +343 -0
  79. package/bin/scalebun.js +1004 -0
  80. package/dist/scalebun.full.js +37348 -0
  81. package/dist/scalebun.slim.js +34137 -0
  82. package/ios/Capture/InteractionTracker.swift +237 -0
  83. package/ios/Capture/PrivacyMaskProcessor.swift +158 -0
  84. package/ios/Capture/ScreenshotCaptureManager.swift +398 -0
  85. package/ios/Capture/WindowResolver.swift +63 -0
  86. package/ios/Core/DeviceIdentity.swift +50 -0
  87. package/ios/Core/ReplayConfig.swift +100 -0
  88. package/ios/Core/ReplayLogger.swift +22 -0
  89. package/ios/Core/SessionIdGenerator.swift +18 -0
  90. package/ios/Crash/ScaleBunCrashBridge.mm +74 -0
  91. package/ios/Crash/ScaleBunCrashHandler.swift +84 -0
  92. package/ios/Crash/ScaleBunCrashModule.swift +98 -0
  93. package/ios/Crash/ScaleBunCrashSignalBridge.h +49 -0
  94. package/ios/Crash/ScaleBunCrashSignalBridge.m +296 -0
  95. package/ios/Crash/ScaleBunCrashSignalStress.c +137 -0
  96. package/ios/Crash/ScaleBunCrashStorage.swift +121 -0
  97. package/ios/Crash/ScaleBunExceptionChain.swift +71 -0
  98. package/ios/CrashTests/ScaleBunExceptionChainTests.swift +144 -0
  99. package/ios/Engage/ScaleBunEngageBridge.m +32 -0
  100. package/ios/Engage/ScaleBunEngageModule.swift +250 -0
  101. package/ios/Engage/ScaleBunPushNotificationCenter.swift +185 -0
  102. package/ios/Ota/BsPatch.swift +203 -0
  103. package/ios/Ota/BundleDownloader.swift +249 -0
  104. package/ios/Ota/DeviceIntegrity.swift +112 -0
  105. package/ios/Ota/DownloadFailure.swift +56 -0
  106. package/ios/Ota/OtaProtocol.swift +246 -0
  107. package/ios/Ota/OtaSlotManager.swift +613 -0
  108. package/ios/Ota/ScaleBunOtaBridge.mm +92 -0
  109. package/ios/Ota/ScaleBunOtaEventsModule.swift +61 -0
  110. package/ios/Ota/ScaleBunOtaKeyRegistry.swift +147 -0
  111. package/ios/Ota/ScaleBunOtaModule.swift +587 -0
  112. package/ios/Ota/ScaleBunOtaReleaseVerifier.swift +119 -0
  113. package/ios/Ota/TlsPinning.swift +222 -0
  114. package/ios/OtaTests/DownloadFailureTests.swift +78 -0
  115. package/ios/OtaTests/ScaleBunOtaVerifierTests.swift +548 -0
  116. package/ios/Outbox/NativeOutbox.swift +632 -0
  117. package/ios/Outbox/OutboxUploader.swift +578 -0
  118. package/ios/Performance/ScaleBunPerformanceBridge.m +32 -0
  119. package/ios/Performance/ScaleBunPerformanceModule.swift +290 -0
  120. package/ios/PrivacyInfo.xcprivacy +97 -0
  121. package/ios/Profiler/ScaleBunProfilerBridge.m +55 -0
  122. package/ios/Profiler/ScaleBunProfilerModule.swift +966 -0
  123. package/ios/ReplaySdk-Bridging-Header.h +2 -0
  124. package/ios/ReplaySdk.swift +793 -0
  125. package/ios/ReplaySdkBridge.m +97 -0
  126. package/ios/Session/SessionManager.swift +273 -0
  127. package/ios/Skan/ScaleBunSkanBridge.m +14 -0
  128. package/ios/Skan/ScaleBunSkanModule.swift +61 -0
  129. package/ios/Storage/ReplayStorage.swift +61 -0
  130. package/ios/Storage/ScaleBunKvFileStore.swift +125 -0
  131. package/ios/Storage/ScaleBunStorageBridge.mm +72 -0
  132. package/ios/Storage/ScaleBunStorageModule.swift +57 -0
  133. package/ios/Transport/ReplayTransport.swift +70 -0
  134. package/ios/VoiceRecorder.swift +145 -0
  135. package/lib/commonjs/analytics/EventTracker.js +598 -0
  136. package/lib/commonjs/analytics/automaticEvents.js +71 -0
  137. package/lib/commonjs/analytics/batching.js +64 -0
  138. package/lib/commonjs/analytics/eventLane.js +55 -0
  139. package/lib/commonjs/analytics/revenue.js +125 -0
  140. package/lib/commonjs/analytics/subscription.js +94 -0
  141. package/lib/commonjs/bootstrap/FeatureRegistry.js +86 -0
  142. package/lib/commonjs/bootstrap/SDKBootstrapper.js +748 -0
  143. package/lib/commonjs/bucketing/fnv1a32.js +45 -0
  144. package/lib/commonjs/compat/codepush.js +153 -0
  145. package/lib/commonjs/config/ConfigManager.js +238 -0
  146. package/lib/commonjs/config/configTypes.js +16 -0
  147. package/lib/commonjs/config/otaPolicyState.js +85 -0
  148. package/lib/commonjs/config/quotaState.js +435 -0
  149. package/lib/commonjs/core/architecture.js +45 -0
  150. package/lib/commonjs/core/clock/now.js +13 -0
  151. package/lib/commonjs/core/config/defaults.js +2 -0
  152. package/lib/commonjs/core/config/schema.js +512 -0
  153. package/lib/commonjs/core/constants/endpoints.js +19 -0
  154. package/lib/commonjs/core/constants/protocol.js +31 -0
  155. package/lib/commonjs/core/constants/timings.js +39 -0
  156. package/lib/commonjs/core/constants/version.js +18 -0
  157. package/lib/commonjs/core/context/app.js +2 -0
  158. package/lib/commonjs/core/context/device.js +155 -0
  159. package/lib/commonjs/core/context/session.js +2 -0
  160. package/lib/commonjs/core/context/user.js +2 -0
  161. package/lib/commonjs/core/contracts/IFeature.js +2 -0
  162. package/lib/commonjs/core/di/container.js +29 -0
  163. package/lib/commonjs/core/encoding/base64.js +50 -0
  164. package/lib/commonjs/core/id/deviceId.js +52 -0
  165. package/lib/commonjs/core/id/installationId.js +55 -0
  166. package/lib/commonjs/core/id/sessionId.js +2 -0
  167. package/lib/commonjs/core/lifecycle/appLifecycle.js +31 -0
  168. package/lib/commonjs/core/lifecycle/crashSafe.js +33 -0
  169. package/lib/commonjs/core/logger/errorClassification.js +107 -0
  170. package/lib/commonjs/core/logger/internalLogger.js +63 -0
  171. package/lib/commonjs/core/logger/levels.js +2 -0
  172. package/lib/commonjs/crypto/hmacSha256.js +132 -0
  173. package/lib/commonjs/debug/bootstrap.js +429 -0
  174. package/lib/commonjs/debug/commands.js +732 -0
  175. package/lib/commonjs/debug/configBuilder.js +70 -0
  176. package/lib/commonjs/debug/exportBridge.js +155 -0
  177. package/lib/commonjs/debug/hostResolver.js +42 -0
  178. package/lib/commonjs/debug/index.js +141 -0
  179. package/lib/commonjs/debug/metrics.js +39 -0
  180. package/lib/commonjs/debug/perf.js +186 -0
  181. package/lib/commonjs/debug/perfWiring.js +109 -0
  182. package/lib/commonjs/debug/protocol.js +121 -0
  183. package/lib/commonjs/debug/redaction.js +422 -0
  184. package/lib/commonjs/debug/replayWiring.js +149 -0
  185. package/lib/commonjs/debug/screenTracking.js +60 -0
  186. package/lib/commonjs/debug/sessionWiring.js +48 -0
  187. package/lib/commonjs/debug/stream.js +542 -0
  188. package/lib/commonjs/debug/transport.js +368 -0
  189. package/lib/commonjs/features/bugreport/BugReportFeature.js +112 -0
  190. package/lib/commonjs/features/bugreport/buildPayload.js +97 -0
  191. package/lib/commonjs/features/bugreport/index.js +2 -0
  192. package/lib/commonjs/features/crash/CrashFeature.js +86 -0
  193. package/lib/commonjs/features/crash/CrashReporter.js +160 -0
  194. package/lib/commonjs/features/crash/NativeCrashFeature.js +42 -0
  195. package/lib/commonjs/features/crash/capture.js +48 -0
  196. package/lib/commonjs/features/crash/globalHandler.js +41 -0
  197. package/lib/commonjs/features/crash/index.js +14 -0
  198. package/lib/commonjs/features/crash/nativeCrashBridge.js +361 -0
  199. package/lib/commonjs/features/crash/rejectionHandler.js +180 -0
  200. package/lib/commonjs/features/crash/scrubCrash.js +158 -0
  201. package/lib/commonjs/features/engage/EngageAnchor.js +132 -0
  202. package/lib/commonjs/features/engage/EngageArchetypeRenderers.js +4292 -0
  203. package/lib/commonjs/features/engage/EngageInAppView.js +2670 -0
  204. package/lib/commonjs/features/engage/EngageInlinePlacement.js +133 -0
  205. package/lib/commonjs/features/engage/EngagePromptProvider.js +1063 -0
  206. package/lib/commonjs/features/engage/EngagePromptView.js +1252 -0
  207. package/lib/commonjs/features/engage/EngageTransport.js +608 -0
  208. package/lib/commonjs/features/engage/EngageVariantContent.js +1778 -0
  209. package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js +54 -0
  210. package/lib/commonjs/features/engage/attachmentCapture.js +48 -0
  211. package/lib/commonjs/features/engage/captureVoiceAttachment.js +88 -0
  212. package/lib/commonjs/features/engage/engageCoachmarkTour.js +106 -0
  213. package/lib/commonjs/features/engage/engageGameLogic.js +308 -0
  214. package/lib/commonjs/features/engage/engageMediaSizing.js +60 -0
  215. package/lib/commonjs/features/engage/engageMultiStepSheet.js +43 -0
  216. package/lib/commonjs/features/engage/engageOutcome.js +118 -0
  217. package/lib/commonjs/features/engage/engagePushTokenBridge.js +72 -0
  218. package/lib/commonjs/features/engage/engageShakeBridge.js +62 -0
  219. package/lib/commonjs/features/engage/engageSignals.js +39 -0
  220. package/lib/commonjs/features/engage/engageStoreReviewBridge.js +49 -0
  221. package/lib/commonjs/features/engage/engageTestSeenStore.js +99 -0
  222. package/lib/commonjs/features/engage/engageThrottle.js +404 -0
  223. package/lib/commonjs/features/engage/engageTriggerEngine.js +365 -0
  224. package/lib/commonjs/features/engage/engageTypes.js +116 -0
  225. package/lib/commonjs/features/engage/engageVariantResolver.js +143 -0
  226. package/lib/commonjs/features/engage/engageWindowInsets.js +98 -0
  227. package/lib/commonjs/features/engage/gestureTriggerDetector.js +85 -0
  228. package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js +55 -0
  229. package/lib/commonjs/features/install-referrer/installReferrer.js +113 -0
  230. package/lib/commonjs/features/journey/ScaleBunDebugRoot.js +1038 -0
  231. package/lib/commonjs/features/journey/ScaleBunFlatList.js +39 -0
  232. package/lib/commonjs/features/journey/ScaleBunImpression.js +113 -0
  233. package/lib/commonjs/features/journey/ScaleBunScrollView.js +102 -0
  234. package/lib/commonjs/features/journey/ScaleBunSectionList.js +39 -0
  235. package/lib/commonjs/features/journey/autoInstrumentScroll.js +161 -0
  236. package/lib/commonjs/features/journey/calibrationContext.js +42 -0
  237. package/lib/commonjs/features/journey/gestureBuffer.js +63 -0
  238. package/lib/commonjs/features/journey/gestureDetector.js +176 -0
  239. package/lib/commonjs/features/journey/impression.js +93 -0
  240. package/lib/commonjs/features/journey/interactionProtocol.js +168 -0
  241. package/lib/commonjs/features/journey/journeyManager.js +466 -0
  242. package/lib/commonjs/features/journey/journeyTypes.js +55 -0
  243. package/lib/commonjs/features/journey/nativeScroll.js +85 -0
  244. package/lib/commonjs/features/journey/navDetector.js +161 -0
  245. package/lib/commonjs/features/journey/screenshotHelper.js +136 -0
  246. package/lib/commonjs/features/journey/scrollContext.js +154 -0
  247. package/lib/commonjs/features/journey/targetGeometry.js +185 -0
  248. package/lib/commonjs/features/journey/targetRegistry.js +53 -0
  249. package/lib/commonjs/features/journey/touchTarget.js +249 -0
  250. package/lib/commonjs/features/journey/uiState.js +188 -0
  251. package/lib/commonjs/features/navigation/AutoScreenDetector.js +607 -0
  252. package/lib/commonjs/features/network/NetworkFeature.js +216 -0
  253. package/lib/commonjs/features/network/index.js +23 -0
  254. package/lib/commonjs/features/network/thirdParty.js +151 -0
  255. package/lib/commonjs/features/ota/OtaEventEmitter.js +129 -0
  256. package/lib/commonjs/features/ota/OtaOrchestrator.js +1309 -0
  257. package/lib/commonjs/features/ota/OtaTypes.js +6 -0
  258. package/lib/commonjs/features/ota/deviceAttributes.js +48 -0
  259. package/lib/commonjs/features/ota/environment.js +172 -0
  260. package/lib/commonjs/features/ota/geoCountry.js +93 -0
  261. package/lib/commonjs/features/ota/retry.js +96 -0
  262. package/lib/commonjs/features/ota/signedDownload.js +187 -0
  263. package/lib/commonjs/features/ota/useOtaUpdate.js +106 -0
  264. package/lib/commonjs/features/performance/PerformanceFeature.js +649 -0
  265. package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js +122 -0
  266. package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js +232 -0
  267. package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js +99 -0
  268. package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js +184 -0
  269. package/lib/commonjs/features/performance/collectors/JsStallCollector.js +165 -0
  270. package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js +59 -0
  271. package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js +78 -0
  272. package/lib/commonjs/features/performance/collectors/UiHangCollector.js +78 -0
  273. package/lib/commonjs/features/performance/config.js +58 -0
  274. package/lib/commonjs/features/performance/getNativePerformanceModule.js +44 -0
  275. package/lib/commonjs/features/performance/index.js +58 -0
  276. package/lib/commonjs/features/performance/metrics/MetricsEngine.js +148 -0
  277. package/lib/commonjs/features/performance/models.js +48 -0
  278. package/lib/commonjs/features/performance/transport/PerformanceTransport.js +168 -0
  279. package/lib/commonjs/features/profiler/ProfilerFeature.js +600 -0
  280. package/lib/commonjs/features/profiler/config.js +151 -0
  281. package/lib/commonjs/features/profiler/contracts.js +62 -0
  282. package/lib/commonjs/features/profiler/index.js +40 -0
  283. package/lib/commonjs/features/profiler/models.js +112 -0
  284. package/lib/commonjs/features/profiler/transport/ProfilerTransport.js +94 -0
  285. package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js +203 -0
  286. package/lib/commonjs/features/replay/bridge/eventEmitter.js +128 -0
  287. package/lib/commonjs/features/replay/bridge/nativeModule.js +95 -0
  288. package/lib/commonjs/features/replay/bridge/nativeQuota.js +121 -0
  289. package/lib/commonjs/features/replay/core/clock/clock.js +47 -0
  290. package/lib/commonjs/features/replay/core/config/defaults.js +88 -0
  291. package/lib/commonjs/features/replay/core/config/validator.js +109 -0
  292. package/lib/commonjs/features/replay/core/env/environmentDetector.js +28 -0
  293. package/lib/commonjs/features/replay/core/errors/safeCall.js +42 -0
  294. package/lib/commonjs/features/replay/core/ids/sessionId.js +53 -0
  295. package/lib/commonjs/features/replay/core/logger/logger.js +36 -0
  296. package/lib/commonjs/features/replay/core/privacy/privacyTypes.js +34 -0
  297. package/lib/commonjs/features/replay/core/queue/boundedQueue.js +71 -0
  298. package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js +259 -0
  299. package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js +139 -0
  300. package/lib/commonjs/features/replay/integrations/network/networkAdapter.js +77 -0
  301. package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js +88 -0
  302. package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js +103 -0
  303. package/lib/commonjs/features/replay/pipeline/batching/batchManager.js +119 -0
  304. package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js +52 -0
  305. package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js +53 -0
  306. package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js +67 -0
  307. package/lib/commonjs/features/replay/public/api.js +336 -0
  308. package/lib/commonjs/features/replay/public/enums.js +85 -0
  309. package/lib/commonjs/features/replay/public/types.js +6 -0
  310. package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js +119 -0
  311. package/lib/commonjs/features/replay/replay/frames/frameModels.js +40 -0
  312. package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js +279 -0
  313. package/lib/commonjs/features/replay/replay/timeline/timelineModels.js +120 -0
  314. package/lib/commonjs/features/replay/transport/BackendReplayTransport.js +175 -0
  315. package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js +75 -0
  316. package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js +124 -0
  317. package/lib/commonjs/features/replay/transport/ReplayTransport.js +2 -0
  318. package/lib/commonjs/features/session/BackendSessionAdapter.js +1915 -0
  319. package/lib/commonjs/features/session/DesktopSessionTransport.js +124 -0
  320. package/lib/commonjs/features/session/JourneyEventPipeline.js +244 -0
  321. package/lib/commonjs/features/session/ReplayCaptureManager.js +1253 -0
  322. package/lib/commonjs/features/session/ScrollTracker.js +147 -0
  323. package/lib/commonjs/features/session/SessionManager.js +1448 -0
  324. package/lib/commonjs/features/session/SyncDecisionEngine.js +95 -0
  325. package/lib/commonjs/features/session/frameLink.js +36 -0
  326. package/lib/commonjs/features/session/frameScrollState.js +41 -0
  327. package/lib/commonjs/features/session/index.js +84 -0
  328. package/lib/commonjs/features/session/nativeCapture.js +53 -0
  329. package/lib/commonjs/features/session/outboxFrameCapture.js +83 -0
  330. package/lib/commonjs/features/session/sessionTypes.js +230 -0
  331. package/lib/commonjs/features/session/viewportPlausibility.js +143 -0
  332. package/lib/commonjs/features/skan/skanBridge.js +54 -0
  333. package/lib/commonjs/features/skan/skanConversionManager.js +134 -0
  334. package/lib/commonjs/index.js +267 -0
  335. package/lib/commonjs/integrations/fetch/fetchInterceptor.js +174 -0
  336. package/lib/commonjs/integrations/navigation/screenTracker.js +2 -0
  337. package/lib/commonjs/integrations/network/bodyCapture.js +336 -0
  338. package/lib/commonjs/integrations/xhr/xhrInterceptor.js +224 -0
  339. package/lib/commonjs/metro/composeSourceMap.js +105 -0
  340. package/lib/commonjs/metro/featureModules.js +131 -0
  341. package/lib/commonjs/metro/index.js +230 -0
  342. package/lib/commonjs/metro/optionalDependencyStub.js +6 -0
  343. package/lib/commonjs/metro/optionalModules.js +31 -0
  344. package/lib/commonjs/metro/serializerCompose.js +161 -0
  345. package/lib/commonjs/pipeline/dispatcher/dispatcher.js +28 -0
  346. package/lib/commonjs/pipeline/envelope/envelope.js +17 -0
  347. package/lib/commonjs/pipeline/envelope/serializer.js +14 -0
  348. package/lib/commonjs/pipeline/processors/dedupe.js +2 -0
  349. package/lib/commonjs/pipeline/processors/enrich.js +16 -0
  350. package/lib/commonjs/pipeline/processors/sampling.js +2 -0
  351. package/lib/commonjs/pipeline/processors/sanitize.js +28 -0
  352. package/lib/commonjs/pipeline/queue/flushQueue.js +107 -0
  353. package/lib/commonjs/pipeline/queue/memoryQueue.js +31 -0
  354. package/lib/commonjs/pipeline/queue/persistentQueue.js +342 -0
  355. package/lib/commonjs/pipeline/queue/queuePolicy.js +2 -0
  356. package/lib/commonjs/pipeline/scheduler/flushScheduler.js +45 -0
  357. package/lib/commonjs/pipeline/scheduler/retryPolicy.js +15 -0
  358. package/lib/commonjs/public/ScaleBunErrorBoundary.js +91 -0
  359. package/lib/commonjs/public/ScaleBunFacade.js +2044 -0
  360. package/lib/commonjs/public/ScaleBunProvider.js +62 -0
  361. package/lib/commonjs/public/typedTracker.js +79 -0
  362. package/lib/commonjs/public/types.js +6 -0
  363. package/lib/commonjs/push/PushManager.js +270 -0
  364. package/lib/commonjs/push/adapters/ManualAdapter.js +86 -0
  365. package/lib/commonjs/push/adapters/NativeBridgeAdapter.js +131 -0
  366. package/lib/commonjs/push/adapters/NoopAdapter.js +45 -0
  367. package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js +248 -0
  368. package/lib/commonjs/push/adapters/loadMessaging.js +29 -0
  369. package/lib/commonjs/push/adapters/loadNotifee.js +36 -0
  370. package/lib/commonjs/push/adapters/selectAdapter.js +153 -0
  371. package/lib/commonjs/push/detect/capabilities.js +136 -0
  372. package/lib/commonjs/push/index.js +33 -0
  373. package/lib/commonjs/push/native/nativeNotifications.js +168 -0
  374. package/lib/commonjs/push/types.js +2 -0
  375. package/lib/commonjs/specs/NativeReplaySdk.js +28 -0
  376. package/lib/commonjs/specs/NativeScaleBunCrash.js +30 -0
  377. package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js +24 -0
  378. package/lib/commonjs/specs/NativeScaleBunOta.js +32 -0
  379. package/lib/commonjs/specs/NativeScaleBunPerformance.js +25 -0
  380. package/lib/commonjs/specs/NativeScaleBunProfiler.js +26 -0
  381. package/lib/commonjs/specs/NativeScaleBunStorage.js +40 -0
  382. package/lib/commonjs/storage/StorageBackend.js +240 -0
  383. package/lib/commonjs/storage/db/sqlite.js +2 -0
  384. package/lib/commonjs/storage/files/fileStore.js +2 -0
  385. package/lib/commonjs/transport/auth/sdkSession.js +28 -0
  386. package/lib/commonjs/transport/backoff/exponentialJitter.js +16 -0
  387. package/lib/commonjs/transport/http/endpoints.js +46 -0
  388. package/lib/commonjs/transport/http/httpClient.js +72 -0
  389. package/lib/commonjs/transport/rateLimit/retryAfter.js +2 -0
  390. package/lib/commonjs/transport/signing/requestSigner.js +2 -0
  391. package/lib/commonjs/vendor/protocol/index.js +327 -0
  392. package/lib/commonjs/vendor/protocol/internal/validation.js +429 -0
  393. package/lib/commonjs/vendor/sdk-contracts/bridge.js +2 -0
  394. package/lib/commonjs/vendor/sdk-contracts/config.js +2 -0
  395. package/lib/commonjs/vendor/sdk-contracts/events.js +2 -0
  396. package/lib/commonjs/vendor/sdk-contracts/features.js +2 -0
  397. package/lib/commonjs/vendor/sdk-contracts/index.js +2 -0
  398. package/lib/commonjs/vendor/sdk-contracts/platform.js +2 -0
  399. package/lib/commonjs/vendor/sdk-contracts/session-boundary.js +6 -0
  400. package/lib/commonjs/vendor/sdk-contracts/session.js +2 -0
  401. package/lib/commonjs/vendor/vendor.manifest +10 -0
  402. package/lib/module/analytics/EventTracker.js +592 -0
  403. package/lib/module/analytics/automaticEvents.js +63 -0
  404. package/lib/module/analytics/batching.js +55 -0
  405. package/lib/module/analytics/eventLane.js +47 -0
  406. package/lib/module/analytics/revenue.js +117 -0
  407. package/lib/module/analytics/subscription.js +86 -0
  408. package/lib/module/bootstrap/FeatureRegistry.js +79 -0
  409. package/lib/module/bootstrap/SDKBootstrapper.js +742 -0
  410. package/lib/module/bucketing/fnv1a32.js +37 -0
  411. package/lib/module/compat/codepush.js +147 -0
  412. package/lib/module/config/ConfigManager.js +230 -0
  413. package/lib/module/config/configTypes.js +10 -0
  414. package/lib/module/config/otaPolicyState.js +76 -0
  415. package/lib/module/config/quotaState.js +423 -0
  416. package/lib/module/core/architecture.js +38 -0
  417. package/lib/module/core/clock/now.js +7 -0
  418. package/lib/module/core/config/defaults.js +2 -0
  419. package/lib/module/core/config/schema.js +506 -0
  420. package/lib/module/core/constants/endpoints.js +13 -0
  421. package/lib/module/core/constants/protocol.js +25 -0
  422. package/lib/module/core/constants/timings.js +26 -0
  423. package/lib/module/core/constants/version.js +12 -0
  424. package/lib/module/core/context/app.js +2 -0
  425. package/lib/module/core/context/device.js +143 -0
  426. package/lib/module/core/context/session.js +2 -0
  427. package/lib/module/core/context/user.js +2 -0
  428. package/lib/module/core/contracts/IFeature.js +2 -0
  429. package/lib/module/core/di/container.js +22 -0
  430. package/lib/module/core/encoding/base64.js +44 -0
  431. package/lib/module/core/id/deviceId.js +45 -0
  432. package/lib/module/core/id/installationId.js +50 -0
  433. package/lib/module/core/id/sessionId.js +2 -0
  434. package/lib/module/core/lifecycle/appLifecycle.js +25 -0
  435. package/lib/module/core/lifecycle/crashSafe.js +26 -0
  436. package/lib/module/core/logger/errorClassification.js +96 -0
  437. package/lib/module/core/logger/internalLogger.js +59 -0
  438. package/lib/module/core/logger/levels.js +2 -0
  439. package/lib/module/crypto/hmacSha256.js +126 -0
  440. package/lib/module/debug/bootstrap.js +393 -0
  441. package/lib/module/debug/commands.js +726 -0
  442. package/lib/module/debug/configBuilder.js +63 -0
  443. package/lib/module/debug/exportBridge.js +148 -0
  444. package/lib/module/debug/hostResolver.js +37 -0
  445. package/lib/module/debug/index.js +13 -0
  446. package/lib/module/debug/metrics.js +33 -0
  447. package/lib/module/debug/perf.js +180 -0
  448. package/lib/module/debug/perfWiring.js +102 -0
  449. package/lib/module/debug/protocol.js +19 -0
  450. package/lib/module/debug/redaction.js +411 -0
  451. package/lib/module/debug/replayWiring.js +139 -0
  452. package/lib/module/debug/screenTracking.js +53 -0
  453. package/lib/module/debug/sessionWiring.js +43 -0
  454. package/lib/module/debug/stream.js +536 -0
  455. package/lib/module/debug/transport.js +362 -0
  456. package/lib/module/features/bugreport/BugReportFeature.js +105 -0
  457. package/lib/module/features/bugreport/buildPayload.js +91 -0
  458. package/lib/module/features/bugreport/index.js +2 -0
  459. package/lib/module/features/crash/CrashFeature.js +79 -0
  460. package/lib/module/features/crash/CrashReporter.js +151 -0
  461. package/lib/module/features/crash/NativeCrashFeature.js +36 -0
  462. package/lib/module/features/crash/capture.js +42 -0
  463. package/lib/module/features/crash/globalHandler.js +36 -0
  464. package/lib/module/features/crash/index.js +8 -0
  465. package/lib/module/features/crash/nativeCrashBridge.js +350 -0
  466. package/lib/module/features/crash/rejectionHandler.js +171 -0
  467. package/lib/module/features/crash/scrubCrash.js +149 -0
  468. package/lib/module/features/engage/EngageAnchor.js +121 -0
  469. package/lib/module/features/engage/EngageArchetypeRenderers.js +4264 -0
  470. package/lib/module/features/engage/EngageInAppView.js +2656 -0
  471. package/lib/module/features/engage/EngageInlinePlacement.js +123 -0
  472. package/lib/module/features/engage/EngagePromptProvider.js +1054 -0
  473. package/lib/module/features/engage/EngagePromptView.js +1243 -0
  474. package/lib/module/features/engage/EngageTransport.js +602 -0
  475. package/lib/module/features/engage/EngageVariantContent.js +1771 -0
  476. package/lib/module/features/engage/__test-support__/reactNativeStub.js +52 -0
  477. package/lib/module/features/engage/attachmentCapture.js +42 -0
  478. package/lib/module/features/engage/captureVoiceAttachment.js +80 -0
  479. package/lib/module/features/engage/engageCoachmarkTour.js +94 -0
  480. package/lib/module/features/engage/engageGameLogic.js +287 -0
  481. package/lib/module/features/engage/engageMediaSizing.js +51 -0
  482. package/lib/module/features/engage/engageMultiStepSheet.js +35 -0
  483. package/lib/module/features/engage/engageOutcome.js +108 -0
  484. package/lib/module/features/engage/engagePushTokenBridge.js +65 -0
  485. package/lib/module/features/engage/engageShakeBridge.js +56 -0
  486. package/lib/module/features/engage/engageSignals.js +34 -0
  487. package/lib/module/features/engage/engageStoreReviewBridge.js +43 -0
  488. package/lib/module/features/engage/engageTestSeenStore.js +92 -0
  489. package/lib/module/features/engage/engageThrottle.js +390 -0
  490. package/lib/module/features/engage/engageTriggerEngine.js +360 -0
  491. package/lib/module/features/engage/engageTypes.js +110 -0
  492. package/lib/module/features/engage/engageVariantResolver.js +135 -0
  493. package/lib/module/features/engage/engageWindowInsets.js +89 -0
  494. package/lib/module/features/engage/gestureTriggerDetector.js +80 -0
  495. package/lib/module/features/engage/transcription/TranscriptionProvider.js +46 -0
  496. package/lib/module/features/install-referrer/installReferrer.js +104 -0
  497. package/lib/module/features/journey/ScaleBunDebugRoot.js +1030 -0
  498. package/lib/module/features/journey/ScaleBunFlatList.js +32 -0
  499. package/lib/module/features/journey/ScaleBunImpression.js +105 -0
  500. package/lib/module/features/journey/ScaleBunScrollView.js +95 -0
  501. package/lib/module/features/journey/ScaleBunSectionList.js +32 -0
  502. package/lib/module/features/journey/autoInstrumentScroll.js +155 -0
  503. package/lib/module/features/journey/calibrationContext.js +35 -0
  504. package/lib/module/features/journey/gestureBuffer.js +56 -0
  505. package/lib/module/features/journey/gestureDetector.js +169 -0
  506. package/lib/module/features/journey/impression.js +84 -0
  507. package/lib/module/features/journey/interactionProtocol.js +158 -0
  508. package/lib/module/features/journey/journeyManager.js +459 -0
  509. package/lib/module/features/journey/journeyTypes.js +49 -0
  510. package/lib/module/features/journey/nativeScroll.js +77 -0
  511. package/lib/module/features/journey/navDetector.js +154 -0
  512. package/lib/module/features/journey/screenshotHelper.js +129 -0
  513. package/lib/module/features/journey/scrollContext.js +142 -0
  514. package/lib/module/features/journey/targetGeometry.js +175 -0
  515. package/lib/module/features/journey/targetRegistry.js +44 -0
  516. package/lib/module/features/journey/touchTarget.js +241 -0
  517. package/lib/module/features/journey/uiState.js +176 -0
  518. package/lib/module/features/navigation/AutoScreenDetector.js +601 -0
  519. package/lib/module/features/network/NetworkFeature.js +209 -0
  520. package/lib/module/features/network/index.js +17 -0
  521. package/lib/module/features/network/thirdParty.js +142 -0
  522. package/lib/module/features/ota/OtaEventEmitter.js +123 -0
  523. package/lib/module/features/ota/OtaOrchestrator.js +1302 -0
  524. package/lib/module/features/ota/OtaTypes.js +2 -0
  525. package/lib/module/features/ota/deviceAttributes.js +43 -0
  526. package/lib/module/features/ota/environment.js +165 -0
  527. package/lib/module/features/ota/geoCountry.js +86 -0
  528. package/lib/module/features/ota/retry.js +87 -0
  529. package/lib/module/features/ota/signedDownload.js +174 -0
  530. package/lib/module/features/ota/useOtaUpdate.js +100 -0
  531. package/lib/module/features/performance/PerformanceFeature.js +643 -0
  532. package/lib/module/features/performance/collectors/AppLaunchCollector.js +115 -0
  533. package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js +225 -0
  534. package/lib/module/features/performance/collectors/CustomTraceCollector.js +92 -0
  535. package/lib/module/features/performance/collectors/FrameMetricsCollector.js +177 -0
  536. package/lib/module/features/performance/collectors/JsStallCollector.js +158 -0
  537. package/lib/module/features/performance/collectors/NetworkPerfCollector.js +52 -0
  538. package/lib/module/features/performance/collectors/ScreenLoadCollector.js +71 -0
  539. package/lib/module/features/performance/collectors/UiHangCollector.js +71 -0
  540. package/lib/module/features/performance/config.js +51 -0
  541. package/lib/module/features/performance/getNativePerformanceModule.js +39 -0
  542. package/lib/module/features/performance/index.js +9 -0
  543. package/lib/module/features/performance/metrics/MetricsEngine.js +139 -0
  544. package/lib/module/features/performance/models.js +42 -0
  545. package/lib/module/features/performance/transport/PerformanceTransport.js +162 -0
  546. package/lib/module/features/profiler/ProfilerFeature.js +594 -0
  547. package/lib/module/features/profiler/config.js +143 -0
  548. package/lib/module/features/profiler/contracts.js +56 -0
  549. package/lib/module/features/profiler/index.js +11 -0
  550. package/lib/module/features/profiler/models.js +106 -0
  551. package/lib/module/features/profiler/transport/ProfilerTransport.js +87 -0
  552. package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js +198 -0
  553. package/lib/module/features/replay/bridge/eventEmitter.js +122 -0
  554. package/lib/module/features/replay/bridge/nativeModule.js +89 -0
  555. package/lib/module/features/replay/bridge/nativeQuota.js +109 -0
  556. package/lib/module/features/replay/core/clock/clock.js +37 -0
  557. package/lib/module/features/replay/core/config/defaults.js +82 -0
  558. package/lib/module/features/replay/core/config/validator.js +103 -0
  559. package/lib/module/features/replay/core/env/environmentDetector.js +22 -0
  560. package/lib/module/features/replay/core/errors/safeCall.js +35 -0
  561. package/lib/module/features/replay/core/ids/sessionId.js +44 -0
  562. package/lib/module/features/replay/core/logger/logger.js +29 -0
  563. package/lib/module/features/replay/core/privacy/privacyTypes.js +27 -0
  564. package/lib/module/features/replay/core/queue/boundedQueue.js +64 -0
  565. package/lib/module/features/replay/integrations/alert/alertInstrumentation.js +252 -0
  566. package/lib/module/features/replay/integrations/logs/consoleIntegration.js +131 -0
  567. package/lib/module/features/replay/integrations/network/networkAdapter.js +70 -0
  568. package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js +82 -0
  569. package/lib/module/features/replay/integrations/touch/ReplayRoot.js +96 -0
  570. package/lib/module/features/replay/pipeline/batching/batchManager.js +113 -0
  571. package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js +43 -0
  572. package/lib/module/features/replay/pipeline/retry/retryPolicy.js +45 -0
  573. package/lib/module/features/replay/pipeline/transport/transportTypes.js +60 -0
  574. package/lib/module/features/replay/public/api.js +332 -0
  575. package/lib/module/features/replay/public/enums.js +85 -0
  576. package/lib/module/features/replay/public/types.js +2 -0
  577. package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js +113 -0
  578. package/lib/module/features/replay/replay/frames/frameModels.js +33 -0
  579. package/lib/module/features/replay/replay/session/sessionOrchestrator.js +272 -0
  580. package/lib/module/features/replay/replay/timeline/timelineModels.js +108 -0
  581. package/lib/module/features/replay/transport/BackendReplayTransport.js +169 -0
  582. package/lib/module/features/replay/transport/CompositeReplayTransport.js +68 -0
  583. package/lib/module/features/replay/transport/DesktopReplayTransport.js +119 -0
  584. package/lib/module/features/replay/transport/ReplayTransport.js +2 -0
  585. package/lib/module/features/session/BackendSessionAdapter.js +1908 -0
  586. package/lib/module/features/session/DesktopSessionTransport.js +118 -0
  587. package/lib/module/features/session/JourneyEventPipeline.js +239 -0
  588. package/lib/module/features/session/ReplayCaptureManager.js +1248 -0
  589. package/lib/module/features/session/ScrollTracker.js +141 -0
  590. package/lib/module/features/session/SessionManager.js +1443 -0
  591. package/lib/module/features/session/SyncDecisionEngine.js +88 -0
  592. package/lib/module/features/session/frameLink.js +29 -0
  593. package/lib/module/features/session/frameScrollState.js +34 -0
  594. package/lib/module/features/session/index.js +35 -0
  595. package/lib/module/features/session/nativeCapture.js +45 -0
  596. package/lib/module/features/session/outboxFrameCapture.js +77 -0
  597. package/lib/module/features/session/sessionTypes.js +226 -0
  598. package/lib/module/features/session/viewportPlausibility.js +137 -0
  599. package/lib/module/features/skan/skanBridge.js +48 -0
  600. package/lib/module/features/skan/skanConversionManager.js +128 -0
  601. package/lib/module/index.js +80 -0
  602. package/lib/module/integrations/fetch/fetchInterceptor.js +169 -0
  603. package/lib/module/integrations/navigation/screenTracker.js +2 -0
  604. package/lib/module/integrations/network/bodyCapture.js +320 -0
  605. package/lib/module/integrations/xhr/xhrInterceptor.js +219 -0
  606. package/lib/module/metro/composeSourceMap.js +97 -0
  607. package/lib/module/metro/featureModules.js +123 -0
  608. package/lib/module/metro/index.js +218 -0
  609. package/lib/module/metro/optionalDependencyStub.js +14 -0
  610. package/lib/module/metro/optionalModules.js +25 -0
  611. package/lib/module/metro/serializerCompose.js +152 -0
  612. package/lib/module/pipeline/dispatcher/dispatcher.js +21 -0
  613. package/lib/module/pipeline/envelope/envelope.js +11 -0
  614. package/lib/module/pipeline/envelope/serializer.js +8 -0
  615. package/lib/module/pipeline/processors/dedupe.js +2 -0
  616. package/lib/module/pipeline/processors/enrich.js +10 -0
  617. package/lib/module/pipeline/processors/sampling.js +2 -0
  618. package/lib/module/pipeline/processors/sanitize.js +22 -0
  619. package/lib/module/pipeline/queue/flushQueue.js +102 -0
  620. package/lib/module/pipeline/queue/memoryQueue.js +24 -0
  621. package/lib/module/pipeline/queue/persistentQueue.js +336 -0
  622. package/lib/module/pipeline/queue/queuePolicy.js +2 -0
  623. package/lib/module/pipeline/scheduler/flushScheduler.js +38 -0
  624. package/lib/module/pipeline/scheduler/retryPolicy.js +9 -0
  625. package/lib/module/public/ScaleBunErrorBoundary.js +82 -0
  626. package/lib/module/public/ScaleBunFacade.js +2038 -0
  627. package/lib/module/public/ScaleBunProvider.js +54 -0
  628. package/lib/module/public/typedTracker.js +72 -0
  629. package/lib/module/public/types.js +2 -0
  630. package/lib/module/push/PushManager.js +263 -0
  631. package/lib/module/push/adapters/ManualAdapter.js +79 -0
  632. package/lib/module/push/adapters/NativeBridgeAdapter.js +124 -0
  633. package/lib/module/push/adapters/NoopAdapter.js +38 -0
  634. package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js +241 -0
  635. package/lib/module/push/adapters/loadMessaging.js +23 -0
  636. package/lib/module/push/adapters/loadNotifee.js +30 -0
  637. package/lib/module/push/adapters/selectAdapter.js +147 -0
  638. package/lib/module/push/detect/capabilities.js +130 -0
  639. package/lib/module/push/index.js +9 -0
  640. package/lib/module/push/native/nativeNotifications.js +155 -0
  641. package/lib/module/push/types.js +2 -0
  642. package/lib/module/specs/NativeReplaySdk.js +24 -0
  643. package/lib/module/specs/NativeScaleBunCrash.js +26 -0
  644. package/lib/module/specs/NativeScaleBunInstallReferrer.js +20 -0
  645. package/lib/module/specs/NativeScaleBunOta.js +28 -0
  646. package/lib/module/specs/NativeScaleBunPerformance.js +21 -0
  647. package/lib/module/specs/NativeScaleBunProfiler.js +22 -0
  648. package/lib/module/specs/NativeScaleBunStorage.js +36 -0
  649. package/lib/module/storage/StorageBackend.js +231 -0
  650. package/lib/module/storage/db/sqlite.js +2 -0
  651. package/lib/module/storage/files/fileStore.js +2 -0
  652. package/lib/module/transport/auth/sdkSession.js +21 -0
  653. package/lib/module/transport/backoff/exponentialJitter.js +10 -0
  654. package/lib/module/transport/http/endpoints.js +40 -0
  655. package/lib/module/transport/http/httpClient.js +64 -0
  656. package/lib/module/transport/rateLimit/retryAfter.js +2 -0
  657. package/lib/module/transport/signing/requestSigner.js +2 -0
  658. package/lib/module/vendor/protocol/index.js +312 -0
  659. package/lib/module/vendor/protocol/internal/validation.js +423 -0
  660. package/lib/module/vendor/sdk-contracts/bridge.js +2 -0
  661. package/lib/module/vendor/sdk-contracts/config.js +2 -0
  662. package/lib/module/vendor/sdk-contracts/events.js +2 -0
  663. package/lib/module/vendor/sdk-contracts/features.js +2 -0
  664. package/lib/module/vendor/sdk-contracts/index.js +2 -0
  665. package/lib/module/vendor/sdk-contracts/platform.js +2 -0
  666. package/lib/module/vendor/sdk-contracts/session-boundary.js +2 -0
  667. package/lib/module/vendor/sdk-contracts/session.js +2 -0
  668. package/lib/module/vendor/vendor.manifest +10 -0
  669. package/lib/typescript/analytics/EventTracker.d.ts +197 -0
  670. package/lib/typescript/analytics/automaticEvents.d.ts +30 -0
  671. package/lib/typescript/analytics/batching.d.ts +33 -0
  672. package/lib/typescript/analytics/eventLane.d.ts +22 -0
  673. package/lib/typescript/analytics/revenue.d.ts +94 -0
  674. package/lib/typescript/analytics/subscription.d.ts +35 -0
  675. package/lib/typescript/bootstrap/FeatureRegistry.d.ts +36 -0
  676. package/lib/typescript/bootstrap/SDKBootstrapper.d.ts +82 -0
  677. package/lib/typescript/bucketing/fnv1a32.d.ts +20 -0
  678. package/lib/typescript/compat/codepush.d.ts +76 -0
  679. package/lib/typescript/config/ConfigManager.d.ts +82 -0
  680. package/lib/typescript/config/configTypes.d.ts +73 -0
  681. package/lib/typescript/config/otaPolicyState.d.ts +55 -0
  682. package/lib/typescript/config/quotaState.d.ts +155 -0
  683. package/lib/typescript/core/architecture.d.ts +29 -0
  684. package/lib/typescript/core/clock/now.d.ts +5 -0
  685. package/lib/typescript/core/config/defaults.d.ts +1 -0
  686. package/lib/typescript/core/config/schema.d.ts +107 -0
  687. package/lib/typescript/core/constants/endpoints.d.ts +13 -0
  688. package/lib/typescript/core/constants/protocol.d.ts +23 -0
  689. package/lib/typescript/core/constants/timings.d.ts +22 -0
  690. package/lib/typescript/core/constants/version.d.ts +12 -0
  691. package/lib/typescript/core/context/app.d.ts +1 -0
  692. package/lib/typescript/core/context/device.d.ts +61 -0
  693. package/lib/typescript/core/context/session.d.ts +1 -0
  694. package/lib/typescript/core/context/user.d.ts +24 -0
  695. package/lib/typescript/core/contracts/IFeature.d.ts +44 -0
  696. package/lib/typescript/core/di/container.d.ts +9 -0
  697. package/lib/typescript/core/encoding/base64.d.ts +13 -0
  698. package/lib/typescript/core/id/deviceId.d.ts +9 -0
  699. package/lib/typescript/core/id/installationId.d.ts +20 -0
  700. package/lib/typescript/core/id/sessionId.d.ts +1 -0
  701. package/lib/typescript/core/lifecycle/appLifecycle.d.ts +14 -0
  702. package/lib/typescript/core/lifecycle/crashSafe.d.ts +7 -0
  703. package/lib/typescript/core/logger/errorClassification.d.ts +46 -0
  704. package/lib/typescript/core/logger/internalLogger.d.ts +24 -0
  705. package/lib/typescript/core/logger/levels.d.ts +1 -0
  706. package/lib/typescript/crypto/hmacSha256.d.ts +10 -0
  707. package/lib/typescript/debug/bootstrap.d.ts +148 -0
  708. package/lib/typescript/debug/commands.d.ts +77 -0
  709. package/lib/typescript/debug/configBuilder.d.ts +13 -0
  710. package/lib/typescript/debug/exportBridge.d.ts +27 -0
  711. package/lib/typescript/debug/hostResolver.d.ts +14 -0
  712. package/lib/typescript/debug/index.d.ts +12 -0
  713. package/lib/typescript/debug/metrics.d.ts +2 -0
  714. package/lib/typescript/debug/perf.d.ts +43 -0
  715. package/lib/typescript/debug/perfWiring.d.ts +33 -0
  716. package/lib/typescript/debug/protocol.d.ts +15 -0
  717. package/lib/typescript/debug/redaction.d.ts +69 -0
  718. package/lib/typescript/debug/replayWiring.d.ts +25 -0
  719. package/lib/typescript/debug/screenTracking.d.ts +16 -0
  720. package/lib/typescript/debug/sessionWiring.d.ts +16 -0
  721. package/lib/typescript/debug/stream.d.ts +77 -0
  722. package/lib/typescript/debug/transport.d.ts +110 -0
  723. package/lib/typescript/features/bugreport/BugReportFeature.d.ts +59 -0
  724. package/lib/typescript/features/bugreport/buildPayload.d.ts +51 -0
  725. package/lib/typescript/features/bugreport/index.d.ts +1 -0
  726. package/lib/typescript/features/crash/CrashFeature.d.ts +21 -0
  727. package/lib/typescript/features/crash/CrashReporter.d.ts +107 -0
  728. package/lib/typescript/features/crash/NativeCrashFeature.d.ts +17 -0
  729. package/lib/typescript/features/crash/capture.d.ts +22 -0
  730. package/lib/typescript/features/crash/globalHandler.d.ts +14 -0
  731. package/lib/typescript/features/crash/index.d.ts +2 -0
  732. package/lib/typescript/features/crash/nativeCrashBridge.d.ts +43 -0
  733. package/lib/typescript/features/crash/rejectionHandler.d.ts +65 -0
  734. package/lib/typescript/features/crash/scrubCrash.d.ts +35 -0
  735. package/lib/typescript/features/engage/EngageAnchor.d.ts +36 -0
  736. package/lib/typescript/features/engage/EngageArchetypeRenderers.d.ts +66 -0
  737. package/lib/typescript/features/engage/EngageInAppView.d.ts +164 -0
  738. package/lib/typescript/features/engage/EngageInlinePlacement.d.ts +42 -0
  739. package/lib/typescript/features/engage/EngagePromptProvider.d.ts +233 -0
  740. package/lib/typescript/features/engage/EngagePromptView.d.ts +97 -0
  741. package/lib/typescript/features/engage/EngageTransport.d.ts +158 -0
  742. package/lib/typescript/features/engage/EngageVariantContent.d.ts +12 -0
  743. package/lib/typescript/features/engage/attachmentCapture.d.ts +17 -0
  744. package/lib/typescript/features/engage/captureVoiceAttachment.d.ts +31 -0
  745. package/lib/typescript/features/engage/engageCoachmarkTour.d.ts +18 -0
  746. package/lib/typescript/features/engage/engageGameLogic.d.ts +34 -0
  747. package/lib/typescript/features/engage/engageMediaSizing.d.ts +23 -0
  748. package/lib/typescript/features/engage/engageMultiStepSheet.d.ts +25 -0
  749. package/lib/typescript/features/engage/engageOutcome.d.ts +38 -0
  750. package/lib/typescript/features/engage/engagePushTokenBridge.d.ts +30 -0
  751. package/lib/typescript/features/engage/engageShakeBridge.d.ts +20 -0
  752. package/lib/typescript/features/engage/engageSignals.d.ts +13 -0
  753. package/lib/typescript/features/engage/engageStoreReviewBridge.d.ts +23 -0
  754. package/lib/typescript/features/engage/engageTestSeenStore.d.ts +46 -0
  755. package/lib/typescript/features/engage/engageThrottle.d.ts +180 -0
  756. package/lib/typescript/features/engage/engageTriggerEngine.d.ts +16 -0
  757. package/lib/typescript/features/engage/engageTypes.d.ts +576 -0
  758. package/lib/typescript/features/engage/engageVariantResolver.d.ts +46 -0
  759. package/lib/typescript/features/engage/engageWindowInsets.d.ts +25 -0
  760. package/lib/typescript/features/engage/gestureTriggerDetector.d.ts +20 -0
  761. package/lib/typescript/features/engage/transcription/TranscriptionProvider.d.ts +51 -0
  762. package/lib/typescript/features/install-referrer/installReferrer.d.ts +39 -0
  763. package/lib/typescript/features/journey/ScaleBunDebugRoot.d.ts +49 -0
  764. package/lib/typescript/features/journey/ScaleBunFlatList.d.ts +20 -0
  765. package/lib/typescript/features/journey/ScaleBunImpression.d.ts +30 -0
  766. package/lib/typescript/features/journey/ScaleBunScrollView.d.ts +25 -0
  767. package/lib/typescript/features/journey/ScaleBunSectionList.d.ts +20 -0
  768. package/lib/typescript/features/journey/autoInstrumentScroll.d.ts +46 -0
  769. package/lib/typescript/features/journey/calibrationContext.d.ts +26 -0
  770. package/lib/typescript/features/journey/gestureBuffer.d.ts +27 -0
  771. package/lib/typescript/features/journey/gestureDetector.d.ts +40 -0
  772. package/lib/typescript/features/journey/impression.d.ts +48 -0
  773. package/lib/typescript/features/journey/interactionProtocol.d.ts +159 -0
  774. package/lib/typescript/features/journey/journeyManager.d.ts +62 -0
  775. package/lib/typescript/features/journey/journeyTypes.d.ts +161 -0
  776. package/lib/typescript/features/journey/nativeScroll.d.ts +47 -0
  777. package/lib/typescript/features/journey/navDetector.d.ts +42 -0
  778. package/lib/typescript/features/journey/screenshotHelper.d.ts +33 -0
  779. package/lib/typescript/features/journey/scrollContext.d.ts +49 -0
  780. package/lib/typescript/features/journey/targetGeometry.d.ts +126 -0
  781. package/lib/typescript/features/journey/targetRegistry.d.ts +28 -0
  782. package/lib/typescript/features/journey/touchTarget.d.ts +174 -0
  783. package/lib/typescript/features/journey/uiState.d.ts +93 -0
  784. package/lib/typescript/features/navigation/AutoScreenDetector.d.ts +196 -0
  785. package/lib/typescript/features/network/NetworkFeature.d.ts +43 -0
  786. package/lib/typescript/features/network/index.d.ts +46 -0
  787. package/lib/typescript/features/network/thirdParty.d.ts +95 -0
  788. package/lib/typescript/features/ota/OtaEventEmitter.d.ts +93 -0
  789. package/lib/typescript/features/ota/OtaOrchestrator.d.ts +287 -0
  790. package/lib/typescript/features/ota/OtaTypes.d.ts +193 -0
  791. package/lib/typescript/features/ota/deviceAttributes.d.ts +18 -0
  792. package/lib/typescript/features/ota/environment.d.ts +99 -0
  793. package/lib/typescript/features/ota/geoCountry.d.ts +14 -0
  794. package/lib/typescript/features/ota/retry.d.ts +53 -0
  795. package/lib/typescript/features/ota/signedDownload.d.ts +81 -0
  796. package/lib/typescript/features/ota/useOtaUpdate.d.ts +72 -0
  797. package/lib/typescript/features/performance/PerformanceFeature.d.ts +132 -0
  798. package/lib/typescript/features/performance/collectors/AppLaunchCollector.d.ts +27 -0
  799. package/lib/typescript/features/performance/collectors/AutoScreenLoadCollector.d.ts +70 -0
  800. package/lib/typescript/features/performance/collectors/CustomTraceCollector.d.ts +35 -0
  801. package/lib/typescript/features/performance/collectors/FrameMetricsCollector.d.ts +74 -0
  802. package/lib/typescript/features/performance/collectors/JsStallCollector.d.ts +45 -0
  803. package/lib/typescript/features/performance/collectors/NetworkPerfCollector.d.ts +23 -0
  804. package/lib/typescript/features/performance/collectors/ScreenLoadCollector.d.ts +30 -0
  805. package/lib/typescript/features/performance/collectors/UiHangCollector.d.ts +21 -0
  806. package/lib/typescript/features/performance/config.d.ts +73 -0
  807. package/lib/typescript/features/performance/getNativePerformanceModule.d.ts +2 -0
  808. package/lib/typescript/features/performance/index.d.ts +10 -0
  809. package/lib/typescript/features/performance/metrics/MetricsEngine.d.ts +69 -0
  810. package/lib/typescript/features/performance/models.d.ts +169 -0
  811. package/lib/typescript/features/performance/transport/PerformanceTransport.d.ts +40 -0
  812. package/lib/typescript/features/profiler/ProfilerFeature.d.ts +92 -0
  813. package/lib/typescript/features/profiler/config.d.ts +85 -0
  814. package/lib/typescript/features/profiler/contracts.d.ts +142 -0
  815. package/lib/typescript/features/profiler/index.d.ts +13 -0
  816. package/lib/typescript/features/profiler/models.d.ts +332 -0
  817. package/lib/typescript/features/profiler/transport/ProfilerTransport.d.ts +30 -0
  818. package/lib/typescript/features/replay/bridge/adapters/bridgeAdapter.d.ts +52 -0
  819. package/lib/typescript/features/replay/bridge/eventEmitter.d.ts +100 -0
  820. package/lib/typescript/features/replay/bridge/nativeModule.d.ts +166 -0
  821. package/lib/typescript/features/replay/bridge/nativeQuota.d.ts +26 -0
  822. package/lib/typescript/features/replay/core/clock/clock.d.ts +16 -0
  823. package/lib/typescript/features/replay/core/config/defaults.d.ts +28 -0
  824. package/lib/typescript/features/replay/core/config/validator.d.ts +13 -0
  825. package/lib/typescript/features/replay/core/env/environmentDetector.d.ts +14 -0
  826. package/lib/typescript/features/replay/core/errors/safeCall.d.ts +12 -0
  827. package/lib/typescript/features/replay/core/ids/sessionId.d.ts +15 -0
  828. package/lib/typescript/features/replay/core/logger/logger.d.ts +15 -0
  829. package/lib/typescript/features/replay/core/privacy/privacyTypes.d.ts +24 -0
  830. package/lib/typescript/features/replay/core/queue/boundedQueue.d.ts +29 -0
  831. package/lib/typescript/features/replay/integrations/alert/alertInstrumentation.d.ts +48 -0
  832. package/lib/typescript/features/replay/integrations/logs/consoleIntegration.d.ts +18 -0
  833. package/lib/typescript/features/replay/integrations/network/networkAdapter.d.ts +31 -0
  834. package/lib/typescript/features/replay/integrations/react-navigation/navigationIntegration.d.ts +25 -0
  835. package/lib/typescript/features/replay/integrations/touch/ReplayRoot.d.ts +26 -0
  836. package/lib/typescript/features/replay/pipeline/batching/batchManager.d.ts +47 -0
  837. package/lib/typescript/features/replay/pipeline/envelope/envelopeBuilder.d.ts +12 -0
  838. package/lib/typescript/features/replay/pipeline/retry/retryPolicy.d.ts +17 -0
  839. package/lib/typescript/features/replay/pipeline/transport/transportTypes.d.ts +40 -0
  840. package/lib/typescript/features/replay/public/api.d.ts +83 -0
  841. package/lib/typescript/features/replay/public/enums.d.ts +73 -0
  842. package/lib/typescript/features/replay/public/types.d.ts +249 -0
  843. package/lib/typescript/features/replay/replay/breadcrumbs/breadcrumbCollector.d.ts +26 -0
  844. package/lib/typescript/features/replay/replay/frames/frameModels.d.ts +23 -0
  845. package/lib/typescript/features/replay/replay/session/sessionOrchestrator.d.ts +53 -0
  846. package/lib/typescript/features/replay/replay/timeline/timelineModels.d.ts +29 -0
  847. package/lib/typescript/features/replay/transport/BackendReplayTransport.d.ts +45 -0
  848. package/lib/typescript/features/replay/transport/CompositeReplayTransport.d.ts +22 -0
  849. package/lib/typescript/features/replay/transport/DesktopReplayTransport.d.ts +35 -0
  850. package/lib/typescript/features/replay/transport/ReplayTransport.d.ts +72 -0
  851. package/lib/typescript/features/session/BackendSessionAdapter.d.ts +528 -0
  852. package/lib/typescript/features/session/DesktopSessionTransport.d.ts +28 -0
  853. package/lib/typescript/features/session/JourneyEventPipeline.d.ts +74 -0
  854. package/lib/typescript/features/session/ReplayCaptureManager.d.ts +391 -0
  855. package/lib/typescript/features/session/ScrollTracker.d.ts +48 -0
  856. package/lib/typescript/features/session/SessionManager.d.ts +414 -0
  857. package/lib/typescript/features/session/SyncDecisionEngine.d.ts +33 -0
  858. package/lib/typescript/features/session/frameLink.d.ts +27 -0
  859. package/lib/typescript/features/session/frameScrollState.d.ts +27 -0
  860. package/lib/typescript/features/session/index.d.ts +23 -0
  861. package/lib/typescript/features/session/nativeCapture.d.ts +18 -0
  862. package/lib/typescript/features/session/outboxFrameCapture.d.ts +20 -0
  863. package/lib/typescript/features/session/sessionTypes.d.ts +362 -0
  864. package/lib/typescript/features/session/viewportPlausibility.d.ts +72 -0
  865. package/lib/typescript/features/skan/skanBridge.d.ts +18 -0
  866. package/lib/typescript/features/skan/skanConversionManager.d.ts +69 -0
  867. package/lib/typescript/index.d.ts +59 -0
  868. package/lib/typescript/integrations/fetch/fetchInterceptor.d.ts +41 -0
  869. package/lib/typescript/integrations/navigation/screenTracker.d.ts +1 -0
  870. package/lib/typescript/integrations/network/bodyCapture.d.ts +101 -0
  871. package/lib/typescript/integrations/xhr/xhrInterceptor.d.ts +46 -0
  872. package/lib/typescript/metro/composeSourceMap.d.ts +26 -0
  873. package/lib/typescript/metro/featureModules.d.ts +49 -0
  874. package/lib/typescript/metro/index.d.ts +99 -0
  875. package/lib/typescript/metro/optionalDependencyStub.d.ts +14 -0
  876. package/lib/typescript/metro/optionalModules.d.ts +20 -0
  877. package/lib/typescript/metro/serializerCompose.d.ts +46 -0
  878. package/lib/typescript/pipeline/dispatcher/dispatcher.d.ts +7 -0
  879. package/lib/typescript/pipeline/envelope/envelope.d.ts +16 -0
  880. package/lib/typescript/pipeline/envelope/serializer.d.ts +7 -0
  881. package/lib/typescript/pipeline/processors/dedupe.d.ts +1 -0
  882. package/lib/typescript/pipeline/processors/enrich.d.ts +3 -0
  883. package/lib/typescript/pipeline/processors/sampling.d.ts +1 -0
  884. package/lib/typescript/pipeline/processors/sanitize.d.ts +3 -0
  885. package/lib/typescript/pipeline/queue/flushQueue.d.ts +12 -0
  886. package/lib/typescript/pipeline/queue/memoryQueue.d.ts +12 -0
  887. package/lib/typescript/pipeline/queue/persistentQueue.d.ts +120 -0
  888. package/lib/typescript/pipeline/queue/queuePolicy.d.ts +1 -0
  889. package/lib/typescript/pipeline/scheduler/flushScheduler.d.ts +9 -0
  890. package/lib/typescript/pipeline/scheduler/retryPolicy.d.ts +5 -0
  891. package/lib/typescript/public/ScaleBunErrorBoundary.d.ts +44 -0
  892. package/lib/typescript/public/ScaleBunFacade.d.ts +800 -0
  893. package/lib/typescript/public/ScaleBunProvider.d.ts +23 -0
  894. package/lib/typescript/public/typedTracker.d.ts +88 -0
  895. package/lib/typescript/public/types.d.ts +316 -0
  896. package/lib/typescript/push/PushManager.d.ts +69 -0
  897. package/lib/typescript/push/adapters/ManualAdapter.d.ts +40 -0
  898. package/lib/typescript/push/adapters/NativeBridgeAdapter.d.ts +37 -0
  899. package/lib/typescript/push/adapters/NoopAdapter.d.ts +21 -0
  900. package/lib/typescript/push/adapters/RNFirebaseMessagingAdapter.d.ts +39 -0
  901. package/lib/typescript/push/adapters/loadMessaging.d.ts +17 -0
  902. package/lib/typescript/push/adapters/loadNotifee.d.ts +15 -0
  903. package/lib/typescript/push/adapters/selectAdapter.d.ts +20 -0
  904. package/lib/typescript/push/detect/capabilities.d.ts +15 -0
  905. package/lib/typescript/push/index.d.ts +10 -0
  906. package/lib/typescript/push/native/nativeNotifications.d.ts +65 -0
  907. package/lib/typescript/push/types.d.ts +143 -0
  908. package/lib/typescript/specs/NativeReplaySdk.d.ts +69 -0
  909. package/lib/typescript/specs/NativeScaleBunCrash.d.ts +58 -0
  910. package/lib/typescript/specs/NativeScaleBunInstallReferrer.d.ts +28 -0
  911. package/lib/typescript/specs/NativeScaleBunOta.d.ts +141 -0
  912. package/lib/typescript/specs/NativeScaleBunPerformance.d.ts +31 -0
  913. package/lib/typescript/specs/NativeScaleBunProfiler.d.ts +38 -0
  914. package/lib/typescript/specs/NativeScaleBunStorage.d.ts +55 -0
  915. package/lib/typescript/storage/StorageBackend.d.ts +131 -0
  916. package/lib/typescript/storage/db/sqlite.d.ts +1 -0
  917. package/lib/typescript/storage/files/fileStore.d.ts +1 -0
  918. package/lib/typescript/transport/auth/sdkSession.d.ts +10 -0
  919. package/lib/typescript/transport/backoff/exponentialJitter.d.ts +5 -0
  920. package/lib/typescript/transport/http/endpoints.d.ts +26 -0
  921. package/lib/typescript/transport/http/httpClient.d.ts +23 -0
  922. package/lib/typescript/transport/rateLimit/retryAfter.d.ts +1 -0
  923. package/lib/typescript/transport/signing/requestSigner.d.ts +1 -0
  924. package/lib/typescript/vendor/protocol/index.d.ts +345 -0
  925. package/lib/typescript/vendor/protocol/internal/validation.d.ts +114 -0
  926. package/lib/typescript/vendor/sdk-contracts/bridge.d.ts +104 -0
  927. package/lib/typescript/vendor/sdk-contracts/config.d.ts +156 -0
  928. package/lib/typescript/vendor/sdk-contracts/events.d.ts +42 -0
  929. package/lib/typescript/vendor/sdk-contracts/features.d.ts +38 -0
  930. package/lib/typescript/vendor/sdk-contracts/index.d.ts +15 -0
  931. package/lib/typescript/vendor/sdk-contracts/platform.d.ts +35 -0
  932. package/lib/typescript/vendor/sdk-contracts/session-boundary.d.ts +42 -0
  933. package/lib/typescript/vendor/sdk-contracts/session.d.ts +157 -0
  934. package/package.json +153 -0
  935. package/react-native.config.js +24 -0
  936. package/scalebun-react-native.podspec +44 -0
  937. package/src/analytics/EventTracker.ts +654 -0
  938. package/src/analytics/automaticEvents.ts +109 -0
  939. package/src/analytics/batching.ts +54 -0
  940. package/src/analytics/eventLane.ts +48 -0
  941. package/src/analytics/revenue.ts +143 -0
  942. package/src/analytics/subscription.ts +145 -0
  943. package/src/bootstrap/FeatureRegistry.ts +81 -0
  944. package/src/bootstrap/SDKBootstrapper.ts +769 -0
  945. package/src/bucketing/fnv1a32.ts +40 -0
  946. package/src/compat/codepush.ts +189 -0
  947. package/src/config/ConfigManager.ts +233 -0
  948. package/src/config/configTypes.ts +62 -0
  949. package/src/config/otaPolicyState.ts +79 -0
  950. package/src/config/quotaState.ts +484 -0
  951. package/src/core/architecture.ts +39 -0
  952. package/src/core/clock/now.ts +6 -0
  953. package/src/core/config/defaults.ts +0 -0
  954. package/src/core/config/schema.ts +455 -0
  955. package/src/core/constants/endpoints.ts +12 -0
  956. package/src/core/constants/protocol.ts +24 -0
  957. package/src/core/constants/timings.ts +25 -0
  958. package/src/core/constants/version.ts +11 -0
  959. package/src/core/context/app.ts +0 -0
  960. package/src/core/context/device.ts +169 -0
  961. package/src/core/context/session.ts +0 -0
  962. package/src/core/context/user.ts +26 -0
  963. package/src/core/contracts/IFeature.ts +53 -0
  964. package/src/core/di/container.ts +26 -0
  965. package/src/core/encoding/base64.ts +46 -0
  966. package/src/core/id/deviceId.ts +51 -0
  967. package/src/core/id/installationId.ts +52 -0
  968. package/src/core/id/sessionId.ts +0 -0
  969. package/src/core/lifecycle/appLifecycle.ts +33 -0
  970. package/src/core/lifecycle/crashSafe.ts +29 -0
  971. package/src/core/logger/errorClassification.ts +108 -0
  972. package/src/core/logger/internalLogger.ts +65 -0
  973. package/src/core/logger/levels.ts +0 -0
  974. package/src/crypto/hmacSha256.ts +106 -0
  975. package/src/debug/bootstrap.ts +436 -0
  976. package/src/debug/commands.ts +597 -0
  977. package/src/debug/configBuilder.ts +56 -0
  978. package/src/debug/exportBridge.ts +155 -0
  979. package/src/debug/hostResolver.ts +34 -0
  980. package/src/debug/index.ts +25 -0
  981. package/src/debug/metrics.ts +29 -0
  982. package/src/debug/perf.ts +212 -0
  983. package/src/debug/perfWiring.ts +119 -0
  984. package/src/debug/protocol.ts +58 -0
  985. package/src/debug/redaction.ts +483 -0
  986. package/src/debug/replayWiring.ts +148 -0
  987. package/src/debug/screenTracking.ts +55 -0
  988. package/src/debug/sessionWiring.ts +59 -0
  989. package/src/debug/stream.ts +561 -0
  990. package/src/debug/transport.ts +440 -0
  991. package/src/features/bugreport/BugReportFeature.ts +128 -0
  992. package/src/features/bugreport/buildPayload.ts +116 -0
  993. package/src/features/bugreport/index.ts +0 -0
  994. package/src/features/crash/CrashFeature.ts +87 -0
  995. package/src/features/crash/CrashReporter.ts +189 -0
  996. package/src/features/crash/NativeCrashFeature.ts +42 -0
  997. package/src/features/crash/capture.ts +48 -0
  998. package/src/features/crash/globalHandler.ts +39 -0
  999. package/src/features/crash/index.ts +8 -0
  1000. package/src/features/crash/nativeCrashBridge.ts +352 -0
  1001. package/src/features/crash/rejectionHandler.ts +196 -0
  1002. package/src/features/crash/scrubCrash.ts +175 -0
  1003. package/src/features/engage/EngageAnchor.tsx +159 -0
  1004. package/src/features/engage/EngageArchetypeRenderers.tsx +3705 -0
  1005. package/src/features/engage/EngageInAppView.tsx +2678 -0
  1006. package/src/features/engage/EngageInlinePlacement.tsx +169 -0
  1007. package/src/features/engage/EngagePromptProvider.tsx +1318 -0
  1008. package/src/features/engage/EngagePromptView.tsx +1400 -0
  1009. package/src/features/engage/EngageTransport.ts +668 -0
  1010. package/src/features/engage/EngageVariantContent.tsx +1483 -0
  1011. package/src/features/engage/__test-support__/reactNativeStub.js +40 -0
  1012. package/src/features/engage/attachmentCapture.ts +45 -0
  1013. package/src/features/engage/captureVoiceAttachment.ts +81 -0
  1014. package/src/features/engage/engageCoachmarkTour.ts +120 -0
  1015. package/src/features/engage/engageGameLogic.ts +347 -0
  1016. package/src/features/engage/engageMediaSizing.ts +76 -0
  1017. package/src/features/engage/engageMultiStepSheet.ts +53 -0
  1018. package/src/features/engage/engageOutcome.ts +157 -0
  1019. package/src/features/engage/engagePushTokenBridge.ts +84 -0
  1020. package/src/features/engage/engageShakeBridge.ts +67 -0
  1021. package/src/features/engage/engageSignals.ts +40 -0
  1022. package/src/features/engage/engageStoreReviewBridge.ts +48 -0
  1023. package/src/features/engage/engageTestSeenStore.ts +95 -0
  1024. package/src/features/engage/engageThrottle.ts +478 -0
  1025. package/src/features/engage/engageTriggerEngine.ts +350 -0
  1026. package/src/features/engage/engageTypes.ts +712 -0
  1027. package/src/features/engage/engageVariantResolver.ts +364 -0
  1028. package/src/features/engage/engageWindowInsets.ts +108 -0
  1029. package/src/features/engage/gestureTriggerDetector.ts +83 -0
  1030. package/src/features/engage/transcription/TranscriptionProvider.ts +68 -0
  1031. package/src/features/install-referrer/installReferrer.ts +112 -0
  1032. package/src/features/journey/ScaleBunDebugRoot.tsx +1045 -0
  1033. package/src/features/journey/ScaleBunFlatList.tsx +39 -0
  1034. package/src/features/journey/ScaleBunImpression.tsx +109 -0
  1035. package/src/features/journey/ScaleBunScrollView.tsx +101 -0
  1036. package/src/features/journey/ScaleBunSectionList.tsx +39 -0
  1037. package/src/features/journey/autoInstrumentScroll.ts +155 -0
  1038. package/src/features/journey/calibrationContext.ts +44 -0
  1039. package/src/features/journey/gestureBuffer.ts +59 -0
  1040. package/src/features/journey/gestureDetector.ts +162 -0
  1041. package/src/features/journey/impression.ts +92 -0
  1042. package/src/features/journey/interactionProtocol.ts +243 -0
  1043. package/src/features/journey/journeyManager.ts +469 -0
  1044. package/src/features/journey/journeyTypes.ts +215 -0
  1045. package/src/features/journey/nativeScroll.ts +94 -0
  1046. package/src/features/journey/navDetector.ts +149 -0
  1047. package/src/features/journey/screenshotHelper.ts +137 -0
  1048. package/src/features/journey/scrollContext.ts +146 -0
  1049. package/src/features/journey/targetGeometry.ts +197 -0
  1050. package/src/features/journey/targetRegistry.ts +43 -0
  1051. package/src/features/journey/touchTarget.ts +339 -0
  1052. package/src/features/journey/uiState.ts +182 -0
  1053. package/src/features/navigation/AutoScreenDetector.ts +617 -0
  1054. package/src/features/network/NetworkFeature.ts +232 -0
  1055. package/src/features/network/index.ts +59 -0
  1056. package/src/features/network/thirdParty.ts +160 -0
  1057. package/src/features/ota/OtaEventEmitter.ts +187 -0
  1058. package/src/features/ota/OtaOrchestrator.ts +1513 -0
  1059. package/src/features/ota/OtaTypes.ts +230 -0
  1060. package/src/features/ota/deviceAttributes.ts +46 -0
  1061. package/src/features/ota/environment.ts +199 -0
  1062. package/src/features/ota/geoCountry.ts +85 -0
  1063. package/src/features/ota/retry.ts +123 -0
  1064. package/src/features/ota/signedDownload.ts +202 -0
  1065. package/src/features/ota/useOtaUpdate.ts +161 -0
  1066. package/src/features/performance/PerformanceFeature.ts +729 -0
  1067. package/src/features/performance/collectors/AppLaunchCollector.ts +131 -0
  1068. package/src/features/performance/collectors/AutoScreenLoadCollector.ts +258 -0
  1069. package/src/features/performance/collectors/CustomTraceCollector.ts +116 -0
  1070. package/src/features/performance/collectors/FrameMetricsCollector.ts +210 -0
  1071. package/src/features/performance/collectors/JsStallCollector.ts +184 -0
  1072. package/src/features/performance/collectors/NetworkPerfCollector.ts +69 -0
  1073. package/src/features/performance/collectors/ScreenLoadCollector.ts +95 -0
  1074. package/src/features/performance/collectors/UiHangCollector.ts +98 -0
  1075. package/src/features/performance/config.ts +136 -0
  1076. package/src/features/performance/getNativePerformanceModule.ts +38 -0
  1077. package/src/features/performance/index.ts +28 -0
  1078. package/src/features/performance/metrics/MetricsEngine.ts +152 -0
  1079. package/src/features/performance/models.ts +235 -0
  1080. package/src/features/performance/transport/PerformanceTransport.ts +161 -0
  1081. package/src/features/profiler/ProfilerFeature.ts +661 -0
  1082. package/src/features/profiler/config.ts +230 -0
  1083. package/src/features/profiler/contracts.ts +176 -0
  1084. package/src/features/profiler/index.ts +45 -0
  1085. package/src/features/profiler/models.ts +430 -0
  1086. package/src/features/profiler/transport/ProfilerTransport.ts +93 -0
  1087. package/src/features/replay/bridge/adapters/bridgeAdapter.ts +235 -0
  1088. package/src/features/replay/bridge/eventEmitter.ts +176 -0
  1089. package/src/features/replay/bridge/nativeModule.ts +252 -0
  1090. package/src/features/replay/bridge/nativeQuota.ts +111 -0
  1091. package/src/features/replay/core/clock/clock.ts +38 -0
  1092. package/src/features/replay/core/config/defaults.ts +66 -0
  1093. package/src/features/replay/core/config/validator.ts +113 -0
  1094. package/src/features/replay/core/env/environmentDetector.ts +21 -0
  1095. package/src/features/replay/core/errors/safeCall.ts +34 -0
  1096. package/src/features/replay/core/ids/sessionId.ts +44 -0
  1097. package/src/features/replay/core/logger/logger.ts +36 -0
  1098. package/src/features/replay/core/privacy/privacyTypes.ts +41 -0
  1099. package/src/features/replay/core/queue/boundedQueue.ts +71 -0
  1100. package/src/features/replay/integrations/alert/alertInstrumentation.ts +277 -0
  1101. package/src/features/replay/integrations/logs/consoleIntegration.ts +136 -0
  1102. package/src/features/replay/integrations/network/networkAdapter.ts +73 -0
  1103. package/src/features/replay/integrations/react-navigation/navigationIntegration.ts +89 -0
  1104. package/src/features/replay/integrations/touch/ReplayRoot.tsx +114 -0
  1105. package/src/features/replay/pipeline/batching/batchManager.ts +133 -0
  1106. package/src/features/replay/pipeline/envelope/envelopeBuilder.ts +66 -0
  1107. package/src/features/replay/pipeline/retry/retryPolicy.ts +62 -0
  1108. package/src/features/replay/pipeline/transport/transportTypes.ts +85 -0
  1109. package/src/features/replay/public/api.ts +364 -0
  1110. package/src/features/replay/public/enums.ts +78 -0
  1111. package/src/features/replay/public/types.ts +297 -0
  1112. package/src/features/replay/replay/breadcrumbs/breadcrumbCollector.ts +115 -0
  1113. package/src/features/replay/replay/frames/frameModels.ts +45 -0
  1114. package/src/features/replay/replay/session/sessionOrchestrator.ts +286 -0
  1115. package/src/features/replay/replay/timeline/timelineModels.ts +129 -0
  1116. package/src/features/replay/transport/BackendReplayTransport.ts +215 -0
  1117. package/src/features/replay/transport/CompositeReplayTransport.ts +82 -0
  1118. package/src/features/replay/transport/DesktopReplayTransport.ts +140 -0
  1119. package/src/features/replay/transport/ReplayTransport.ts +84 -0
  1120. package/src/features/session/BackendSessionAdapter.ts +1977 -0
  1121. package/src/features/session/DesktopSessionTransport.ts +130 -0
  1122. package/src/features/session/JourneyEventPipeline.ts +278 -0
  1123. package/src/features/session/ReplayCaptureManager.ts +1401 -0
  1124. package/src/features/session/ScrollTracker.ts +166 -0
  1125. package/src/features/session/SessionManager.ts +1687 -0
  1126. package/src/features/session/SyncDecisionEngine.ts +117 -0
  1127. package/src/features/session/frameLink.ts +41 -0
  1128. package/src/features/session/frameScrollState.ts +36 -0
  1129. package/src/features/session/index.ts +88 -0
  1130. package/src/features/session/nativeCapture.ts +43 -0
  1131. package/src/features/session/outboxFrameCapture.ts +79 -0
  1132. package/src/features/session/sessionTypes.ts +528 -0
  1133. package/src/features/session/viewportPlausibility.ts +134 -0
  1134. package/src/features/skan/skanBridge.ts +53 -0
  1135. package/src/features/skan/skanConversionManager.ts +173 -0
  1136. package/src/index.ts +206 -0
  1137. package/src/integrations/fetch/fetchInterceptor.ts +201 -0
  1138. package/src/integrations/navigation/screenTracker.ts +0 -0
  1139. package/src/integrations/network/bodyCapture.ts +328 -0
  1140. package/src/integrations/xhr/xhrInterceptor.ts +259 -0
  1141. package/src/metro/composeSourceMap.ts +104 -0
  1142. package/src/metro/featureModules.ts +143 -0
  1143. package/src/metro/index.ts +336 -0
  1144. package/src/metro/optionalDependencyStub.ts +13 -0
  1145. package/src/metro/optionalModules.ts +27 -0
  1146. package/src/metro/serializerCompose.ts +193 -0
  1147. package/src/pipeline/dispatcher/dispatcher.ts +22 -0
  1148. package/src/pipeline/envelope/envelope.ts +31 -0
  1149. package/src/pipeline/envelope/serializer.ts +14 -0
  1150. package/src/pipeline/processors/dedupe.ts +0 -0
  1151. package/src/pipeline/processors/enrich.ts +11 -0
  1152. package/src/pipeline/processors/sampling.ts +0 -0
  1153. package/src/pipeline/processors/sanitize.ts +23 -0
  1154. package/src/pipeline/queue/flushQueue.ts +144 -0
  1155. package/src/pipeline/queue/memoryQueue.ts +31 -0
  1156. package/src/pipeline/queue/persistentQueue.ts +385 -0
  1157. package/src/pipeline/queue/queuePolicy.ts +0 -0
  1158. package/src/pipeline/scheduler/flushScheduler.ts +47 -0
  1159. package/src/pipeline/scheduler/retryPolicy.ts +8 -0
  1160. package/src/public/ScaleBunErrorBoundary.tsx +91 -0
  1161. package/src/public/ScaleBunFacade.ts +2129 -0
  1162. package/src/public/ScaleBunProvider.tsx +91 -0
  1163. package/src/public/typedTracker.ts +123 -0
  1164. package/src/public/types.ts +362 -0
  1165. package/src/push/PushManager.ts +318 -0
  1166. package/src/push/adapters/ManualAdapter.ts +100 -0
  1167. package/src/push/adapters/NativeBridgeAdapter.ts +142 -0
  1168. package/src/push/adapters/NoopAdapter.ts +46 -0
  1169. package/src/push/adapters/RNFirebaseMessagingAdapter.ts +271 -0
  1170. package/src/push/adapters/loadMessaging.ts +24 -0
  1171. package/src/push/adapters/loadNotifee.ts +29 -0
  1172. package/src/push/adapters/selectAdapter.ts +176 -0
  1173. package/src/push/detect/capabilities.ts +124 -0
  1174. package/src/push/index.ts +22 -0
  1175. package/src/push/native/nativeNotifications.ts +207 -0
  1176. package/src/push/types.ts +159 -0
  1177. package/src/specs/NativeReplaySdk.ts +101 -0
  1178. package/src/specs/NativeScaleBunCrash.ts +64 -0
  1179. package/src/specs/NativeScaleBunInstallReferrer.ts +29 -0
  1180. package/src/specs/NativeScaleBunOta.ts +154 -0
  1181. package/src/specs/NativeScaleBunPerformance.ts +34 -0
  1182. package/src/specs/NativeScaleBunProfiler.ts +41 -0
  1183. package/src/specs/NativeScaleBunStorage.ts +59 -0
  1184. package/src/storage/StorageBackend.ts +272 -0
  1185. package/src/storage/db/sqlite.ts +0 -0
  1186. package/src/storage/files/fileStore.ts +0 -0
  1187. package/src/transport/auth/sdkSession.ts +27 -0
  1188. package/src/transport/backoff/exponentialJitter.ts +9 -0
  1189. package/src/transport/http/endpoints.ts +33 -0
  1190. package/src/transport/http/httpClient.ts +73 -0
  1191. package/src/transport/rateLimit/retryAfter.ts +0 -0
  1192. package/src/transport/signing/requestSigner.ts +0 -0
  1193. package/src/vendor/protocol/index.ts +391 -0
  1194. package/src/vendor/protocol/internal/validation.ts +497 -0
  1195. package/src/vendor/sdk-contracts/bridge.ts +162 -0
  1196. package/src/vendor/sdk-contracts/config.ts +192 -0
  1197. package/src/vendor/sdk-contracts/events.ts +50 -0
  1198. package/src/vendor/sdk-contracts/features.ts +42 -0
  1199. package/src/vendor/sdk-contracts/index.ts +98 -0
  1200. package/src/vendor/sdk-contracts/platform.ts +42 -0
  1201. package/src/vendor/sdk-contracts/session-boundary.ts +55 -0
  1202. package/src/vendor/sdk-contracts/session.ts +225 -0
  1203. package/src/vendor/vendor.manifest +10 -0
@@ -0,0 +1,1302 @@
1
+ import { AppState, DeviceEventEmitter, DevSettings, NativeEventEmitter, NativeModules, Platform } from 'react-native';
2
+ import { logger } from '../../core/logger/internalLogger';
3
+ import { noThrow } from '../../core/lifecycle/crashSafe';
4
+ import NativeScaleBunOta from '../../specs/NativeScaleBunOta';
5
+ import { otaEventEmitter } from './OtaEventEmitter';
6
+ import { getDeviceCountry, prefetchDeviceCountry } from './geoCountry';
7
+ import { deviceTargetingAttributes } from './deviceAttributes';
8
+ import { resolveInstallationId } from '../../core/id/installationId';
9
+ import { detectOtaEnvironment } from './environment';
10
+ import { retryWithBackoff, isRetryableNetworkError, HttpStatusError } from './retry';
11
+ import { stageSignedWithRetry, verdictErrorCode, signedPatchSupported, trySignedPatch } from './signedDownload';
12
+ import { createStorageBackend } from '../../storage/StorageBackend';
13
+ import { resolveMobileOS } from '../../core/context/device';
14
+
15
+ /**
16
+ * Identity marker injected into the bundle by `scalebun ota publish` before
17
+ * Hermes compilation. Lets the SDK prove that the bundle it *installed* is the
18
+ * bundle actually *running* — see `verifyRunningBundleIdentity`.
19
+ */
20
+ function readRunningBundleMarker() {
21
+ try {
22
+ const id = globalThis.__SCALEBUN_OTA_ID__;
23
+ return typeof id === 'string' && id.length > 0 ? id : null;
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Download progress: native → JS → (hook + backend live tracker).
31
+ *
32
+ * Both native downloaders emit throttled `ScaleBunOtaProgress` ticks — Android
33
+ * over `RCTDeviceEventEmitter`, iOS via the `ScaleBunOtaEvents` RCTEventEmitter.
34
+ * This subscribes for the duration of one download. Until this existed, the
35
+ * hook's `downloadProgress` and the backend's `/sdk/ota/progress` +
36
+ * live-downloads dashboard were declared on both ends and connected by
37
+ * NOTHING — the tracker had never received a single real row.
38
+ */
39
+
40
+ function subscribeNativeProgress(onTick) {
41
+ try {
42
+ if (Platform.OS === 'ios') {
43
+ const eventsModule = NativeModules.ScaleBunOtaEvents;
44
+ if (!eventsModule) return () => {};
45
+ const emitter = new NativeEventEmitter(eventsModule);
46
+ const sub = emitter.addListener('ScaleBunOtaProgress', onTick);
47
+ return () => sub.remove();
48
+ }
49
+ const sub = DeviceEventEmitter.addListener('ScaleBunOtaProgress', onTick);
50
+ return () => sub.remove();
51
+ } catch {
52
+ return () => {};
53
+ }
54
+ }
55
+
56
+ /** POST at most once per this interval; first and terminal ticks always go. */
57
+ const PROGRESS_POST_INTERVAL_MS = 1_000;
58
+
59
+ /**
60
+ * Deliver queued OTA lifecycle events to the backend's batch endpoint.
61
+ *
62
+ * ── Why the orchestrator owns this ──────────────────────────────────────────
63
+ *
64
+ * `otaEventEmitter.setFlushCallback` documents itself as "called by the SDK
65
+ * core to wire into the existing batch transport" — and nothing, anywhere,
66
+ * ever called it. `flush()` drained the queue into a null callback, so every
67
+ * OTA event the real SDK ever emitted was silently discarded in-process.
68
+ * All 129 ota_events rows in the dev database came from the test app's
69
+ * SIMULATOR; the funnel, adoption charts, and guard thresholds had never seen
70
+ * one byte of real-device telemetry.
71
+ *
72
+ * Owning delivery here (with the params sync() already has) instead of relying
73
+ * on bootstrap wiring means OTA telemetry works in every integration shape —
74
+ * full SDK, standalone orchestrator, CodePush shim — because the component
75
+ * that EMITS the events is the component that delivers them.
76
+ */
77
+ async function deliverOtaEvents(params) {
78
+ const events = otaEventEmitter.flush();
79
+ if (!events.length) return;
80
+ // A platform OTA cannot serve is not reported as Android — it is not reported at all.
81
+ const mobileOS = resolveMobileOS();
82
+ if (!mobileOS) return;
83
+ const items = events.map(e => ({
84
+ kind: 'ota_event',
85
+ type: e.type,
86
+ bundleId: e.bundleId,
87
+ // Without this the backend stored a null releaseId on every row it ingested,
88
+ // while serving the release id on every check — so the delivery funnel could
89
+ // only ever be grouped by bundle, and a bundle re-promoted under a second
90
+ // release merged the two into one indistinguishable series.
91
+ releaseId: e.releaseId,
92
+ installationId: params.installationId,
93
+ // OTA bundles are compiled per platform, so this genuinely is ios|android. Narrowed via
94
+ // resolveMobileOS so a non-mobile RN target is skipped rather than served an Android bundle.
95
+ platform: mobileOS,
96
+ appVersion: params.appVersion,
97
+ durationMs: e.durationMs,
98
+ errorCode: e.error ?? e.reason,
99
+ patchUsed: e.patchUsed,
100
+ timestamp: e.timestamp
101
+ }));
102
+ try {
103
+ const base = params.apiUrl.replace(/\/+$/, '');
104
+ // The batch lane is session-scoped for replay items; OTA rows carry their
105
+ // own installationId and ignore the session, so a synthetic id is correct.
106
+ const res = await fetch(`${base}/ingestion/sessions/ota-${params.installationId}/batch`, {
107
+ method: 'POST',
108
+ headers: {
109
+ 'Content-Type': 'application/json',
110
+ 'x-scalebun-client-key': params.clientKey
111
+ },
112
+ body: JSON.stringify({
113
+ items
114
+ })
115
+ });
116
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
117
+ logger.debug(`[OTA] Delivered ${items.length} telemetry event(s)`);
118
+ } catch (err) {
119
+ // Failed delivery must not fail the update — but the events must not be
120
+ // lost either: requeue so the next sync retries them.
121
+ for (const e of events) otaEventEmitter.emit(e);
122
+ logger.debug(`[OTA] Telemetry delivery failed (will retry next sync): ${err?.message}`);
123
+ }
124
+ }
125
+
126
+ /** Boot-guard configuration */
127
+
128
+ import { resolveCompromisedDevicePolicy } from '../../config/otaPolicyState';
129
+ const DEFAULT_HEALTHY_AFTER_MS = 10_000;
130
+ export class OtaOrchestrator {
131
+ enabled = false;
132
+ currentBundle = null;
133
+
134
+ /**
135
+ * The bundle this process is running, once hydrated from the native slots.
136
+ * Read-only view for integrations (e.g. the CodePush shim's
137
+ * getUpdateMetadata) that need to report the running version.
138
+ */
139
+ getCurrentBundle() {
140
+ return this.currentBundle;
141
+ }
142
+ isRestartRequiredState = false;
143
+
144
+ /**
145
+ * The sync currently running, if any. sync() had NO concurrency control:
146
+ * every caller started a full check/download/stage/apply cycle against the
147
+ * SAME slot directories. Two of them overlapping is not a wasted request,
148
+ * it is a corrupted install — native stage() ends with "remove next/,
149
+ * rename tmp -> next/" while apply() is doing "move next/ -> current/", so
150
+ * one racing the other throws and apply() can leave NO current/ slot at
151
+ * all. A host with a screen that syncs on mount and another that syncs on
152
+ * foreground reproduces this in seconds; on 2026-09-21 it cost two devices
153
+ * that could only be recovered by reinstalling.
154
+ */
155
+ syncInFlight = null;
156
+
157
+ /** When the last network check actually went out (see MIN_CHECK_INTERVAL_MS). */
158
+ lastCheckAt = 0;
159
+
160
+ /**
161
+ * A bundle that is staged and waiting for its restart.
162
+ *
163
+ * Kept SEPARATE from `currentBundle`, which must keep naming the bundle
164
+ * this process is actually executing. Overwriting `currentBundle` at apply
165
+ * time told the server the device was already running code it had never
166
+ * run, so the next check was answered with the NEXT release instead of
167
+ * "up to date" — which is how a single launch chained three installs. It
168
+ * also mis-attributed every CHECK and BOOT_SUCCESS event to a bundle the
169
+ * device had not booted.
170
+ */
171
+ pendingBundle = null;
172
+ /** Root/jailbreak indicators observed at init; empty when none found. */
173
+ integrityIndicators = [];
174
+ /**
175
+ * The native detector was actually asked and answered on this launch.
176
+ *
177
+ * Kept separate from an empty `integrityIndicators` because the two are not
178
+ * the same fact: `false` means never measured (no native module, or the read
179
+ * threw), `true` with an empty list means measured and clean. Reporting the
180
+ * first as the second would show an unmeasured fleet as a clean one.
181
+ */
182
+ integrityMeasured = false;
183
+ healthyTimer = null;
184
+ bootGuardConfig = {};
185
+ environment = null;
186
+ /** One-time boot checks have run in this process (init is idempotent). */
187
+ initialized = false;
188
+ storageBackend = null;
189
+
190
+ /**
191
+ * Initialize the orchestrator. Checks for boot-guard recovery state.
192
+ *
193
+ * Signature enforcement is no longer a JS concern: signed releases are
194
+ * verified and staged in NATIVE code against RSA keys embedded in the app
195
+ * package (SB-OTA-RSA-SHA256-V1), and unsigned releases keep working on
196
+ * SHA-256 integrity alone. There is nothing for the host to configure here.
197
+ */
198
+ init(config) {
199
+ noThrow(() => {
200
+ // Idempotent: init() runs its one-time checks ONCE per process. Found
201
+ // live — a host that calls init() again after installing an update (any
202
+ // retry/re-entry path does this) re-runs the identity verification in a
203
+ // process whose running JS legitimately predates the install, producing
204
+ // a false "INSTALL DID NOT TAKE EFFECT" alarm. The boot-time checks are
205
+ // only meaningful in a fresh process; a second init() must not repeat
206
+ // them. Config is still refreshed so late signature setup works.
207
+ if (this.initialized) {
208
+ this.bootGuardConfig = config ?? this.bootGuardConfig;
209
+ return;
210
+ }
211
+ if (!NativeScaleBunOta) {
212
+ logger.warn('[OTA] NativeScaleBunOta module unavailable — OTA disabled');
213
+ return;
214
+ }
215
+
216
+ // ── RUNTIME GATE ─────────────────────────────────────────────────────
217
+ // Refuse to run on a runtime where the install would silently no-op.
218
+ // See environment.ts: bridgeless below RN 0.76.1 ignores
219
+ // getJSBundleFile() entirely, so a bundle installs, reports INSTALLED,
220
+ // and the app keeps running the APK asset. Staying loudly disabled is
221
+ // strictly better than reporting success that never happened — those
222
+ // false INSTALLED rows feed adoption metrics and guard thresholds.
223
+ this.environment = detectOtaEnvironment();
224
+ if (!this.environment.supported) {
225
+ logger.error(`[OTA] DISABLED — ${this.environment.blockReason}`);
226
+ this.enabled = false;
227
+ return;
228
+ }
229
+ if (this.environment.bridgeless && !this.environment.rnVersion) {
230
+ logger.warn('[OTA] Running bridgeless but the React Native version could not be determined. ' + 'If this app is below RN 0.76.1, OTA updates will install and never load.');
231
+ }
232
+ if (this.environment.requiresReactHostIntegration) {
233
+ // RN 0.82 removed ReactNativeHost, so the legacy
234
+ // `override fun getJSBundleFile()` integration does not exist there.
235
+ // We cannot see which form the host used — the identity check after
236
+ // restart is what proves it — but naming the right fix up front turns
237
+ // a confusing silent failure into a one-line correction.
238
+ logger.debug('[OTA] React Native >= 0.82 detected. The only valid Android integration is ' + 'getDefaultReactHost(..., jsBundleFilePath = ScaleBunOtaModule.getJSBundleFile(ctx)) — ' + 'ReactNativeHost and its getJSBundleFile() override no longer exist.');
239
+ }
240
+ this.initialized = true;
241
+ this.enabled = true;
242
+
243
+ // Config lands BEFORE the integrity read, so the log below can state the
244
+ // policy that will actually be applied rather than assume the default.
245
+ // (It used to be assigned after; the boot-guard heartbeat hit the same
246
+ // ordering bug once and silently fell back to the default window.)
247
+ this.bootGuardConfig = config ?? {};
248
+
249
+ // Device integrity signal.
250
+ //
251
+ // Reported, not enforced. Root defeats any check made from inside the app,
252
+ // so this is not a boundary — it is context. It tells an operator that a
253
+ // device's OTA slot is writable by other processes, which is what makes the
254
+ // launch-time hash re-check in SlotManager meaningful rather than paranoid.
255
+ //
256
+ // A host app that wants to act on it sets `onCompromisedDevice:
257
+ // 'withhold'` (default `'allow'` — see BootGuardConfig), or reads
258
+ // `deviceIntegrityIndicators()` and decides for itself. The DETECTION here
259
+ // is unconditional either way; only the decision downstream changes.
260
+ try {
261
+ const raw = NativeScaleBunOta?.getDeviceIntegrity?.();
262
+ this.integrityIndicators = raw ? JSON.parse(raw) : [];
263
+ // Only a string the detector actually returned counts as a measurement;
264
+ // an absent method (older native, unsupported platform) leaves this
265
+ // false so the check request omits the field instead of claiming clean.
266
+ this.integrityMeasured = typeof raw === 'string';
267
+ if (this.integrityIndicators.length > 0) {
268
+ logger.warn(`[OTA] Device integrity indicators present: ${this.integrityIndicators.join(', ')}. ` + (this.shouldWithhold() ? "onCompromisedDevice is 'withhold' — this device will NOT be offered or " + 'installed any update while the indicators persist.' : 'Updates still install and are still signature-verified, but an installed ' + 'bundle on this device can be modified by other privileged processes. ' + "Set ota.onCompromisedDevice: 'withhold' to stop updating such devices."));
269
+ }
270
+ } catch {
271
+ this.integrityIndicators = [];
272
+ this.integrityMeasured = false;
273
+ }
274
+ logger.debug(`[OTA] Orchestrator initialized (RN ${this.environment.rnVersionString ?? 'unknown'}` + `${this.environment.bridgeless ? ', bridgeless' : ''}` + `${this.environment.hermes ? `, Hermes HBC v${this.environment.hermesBytecodeVersion ?? '?'}` : ''})`);
275
+
276
+ // ONE read of the slot state, shared by both boot-time consumers.
277
+ //
278
+ // `getSlotState()` is CONSUME-ON-READ for the revert record: both native
279
+ // implementations delete it as they serialise, so that a rollback is
280
+ // reported exactly once instead of on every launch forever. Calling it
281
+ // twice therefore means the second caller never sees the revert — which is
282
+ // precisely what happened, since hydration ran first and swallowed it. It
283
+ // is also a blocking synchronous bridge call, so one read is cheaper.
284
+ const slotState = this.readSlotState();
285
+
286
+ // Rehydrate which bundle we are running from the native slot state.
287
+ // Without this `currentBundle` stays null for the whole process after a
288
+ // restart, so every check reported no current bundle and the backend had
289
+ // no way to know what the device was actually on.
290
+ this.hydrateCurrentBundleFromSlots(slotState);
291
+
292
+ // Warm the device-country cache (edge Worker lookup) so checks can carry
293
+ // a country when the API itself sits behind no geo-stamping CDN.
294
+ // Fire-and-forget and failure-soft — a check without a country is valid.
295
+ void prefetchDeviceCountry();
296
+
297
+ // Check if the boot guard fired on this launch (native reverted before JS
298
+ // loaded). BEFORE the identity check, because both read the install record
299
+ // and the identity check retires it — a revert must get its chance to name
300
+ // the bundle that failed while the record still describes it.
301
+ this.checkBootGuardRecovery(slotState);
302
+
303
+ // Prove the bundle we installed is the bundle that loaded.
304
+ this.verifyRunningBundleIdentity();
305
+
306
+ // Boot-guard health is a LOCAL fact: this process booted from the staged
307
+ // bundle and did not crash. The heartbeat used to start only on the
308
+ // `action === 'NONE'` branch of sync(), so confirming a good bundle needed
309
+ // a successful network round-trip that returned exactly that answer — a
310
+ // device offline, rate-limited, or still being offered an update could
311
+ // never clear its marker, and the guard reverted a bundle that was working.
312
+ //
313
+ // It runs HERE, last, and is handed the slot state that was already read.
314
+ // Starting it earlier made it call getSlotState() itself, and that read is
315
+ // consume-on-read for the revert record — it swallowed the revert before
316
+ // checkBootGuardRecovery() could name the bundle that failed, so a
317
+ // crash-rollback went unreported. It also read bootGuardConfig before
318
+ // init() had assigned it, so healthyAfterMs silently fell back to the
319
+ // default.
320
+ this.startBootGuardHeartbeat(slotState);
321
+ });
322
+ }
323
+
324
+ /**
325
+ * Read the active slot back into `currentBundle` so the next check reports
326
+ * what this device is genuinely running.
327
+ */
328
+ /**
329
+ * Parse the native slot state once. Returns null when the module is absent or
330
+ * the payload is unreadable — every caller treats that as "factory bundle".
331
+ */
332
+ readSlotState() {
333
+ if (!NativeScaleBunOta) return null;
334
+ try {
335
+ return JSON.parse(NativeScaleBunOta.getSlotState());
336
+ } catch {
337
+ return null;
338
+ }
339
+ }
340
+ hydrateCurrentBundleFromSlots(state) {
341
+ try {
342
+ const current = state?.current;
343
+ if (!current?.sha256) return;
344
+
345
+ // Keyed on sha256, NOT bundleId. The native `stageBundle` is never told
346
+ // the bundleId — it writes a meta.json containing only `sha256` and
347
+ // `installedAt` — so `current.bundleId` is always absent. Hydrating from
348
+ // it left `currentBundle` null on every launch, which meant the device
349
+ // never told the server what it was running and the server re-offered
350
+ // the same bundle forever. sha256 is the field that is actually there.
351
+ const record = this.readInstallRecord();
352
+ if (record && record.sha256 === current.sha256) {
353
+ this.currentBundle = {
354
+ id: record.bundleId,
355
+ version: record.version,
356
+ releaseId: record.releaseId ?? undefined,
357
+ sha256: record.sha256
358
+ };
359
+ logger.debug(`[OTA] Running bundle v${record.version} (${record.bundleId})`);
360
+ return;
361
+ }
362
+
363
+ // An OTA bundle is installed but we have no record of installing it —
364
+ // a reinstall of the app, cleared storage, or a bundle staged by an
365
+ // older SDK. Report the hash so the server can still recognise it.
366
+ this.currentBundle = {
367
+ sha256: current.sha256
368
+ };
369
+ logger.debug(`[OTA] Running an OTA bundle (sha ${String(current.sha256).slice(0, 12)}…) with no local install record.`);
370
+ } catch {
371
+ // Slot state unreadable — treat as factory bundle.
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Compare the bundle the slot manager believes is active against the identity
377
+ * marker compiled into the bundle that actually loaded.
378
+ *
379
+ * A mismatch means the install path reported success while the runtime kept
380
+ * executing different code — the silent no-op this whole guard exists for.
381
+ * It is reported as APPLY_FAILED, because that is what happened, regardless
382
+ * of what the previous session's telemetry claimed.
383
+ *
384
+ * The expectation recorded at install time is what makes this conclusive.
385
+ * Without it, a missing marker is ambiguous — it could be a bundle published
386
+ * before markers existed, or an install that never took effect. Having
387
+ * written down "this bundle definitely carries marker X" before restarting,
388
+ * a missing marker afterwards can only mean the second.
389
+ */
390
+ verifyRunningBundleIdentity() {
391
+ if (!this.currentBundle) return;
392
+ const running = readRunningBundleMarker();
393
+ const record = this.readInstallRecord();
394
+
395
+ // No record at all — installed by an SDK that predates install records, or
396
+ // local storage was cleared. NOTHING can be concluded here and nothing is
397
+ // reported: the marker is a random per-publish token, never the bundle id,
398
+ // so comparing the two would flag a false mismatch on every healthy launch.
399
+ if (!record) return;
400
+
401
+ // The record describes a bundle that is no longer the active one (a revert,
402
+ // or a bundle staged by another path). It cannot verify this launch, and
403
+ // keeping it would make the next launch mis-report what is running.
404
+ if (record.sha256 !== this.currentBundle.sha256) {
405
+ this.clearInstallExpectation();
406
+ return;
407
+ }
408
+
409
+ // Already proven on an earlier launch. The token is retired once verified
410
+ // while the REST of the record stays — it is also the sha256 -> bundleId map
411
+ // that `hydrateCurrentBundleFromSlots` reads to report what this device is
412
+ // running. Wiping the whole record here is what made every launch after the
413
+ // first send `currentBundleId: undefined`, which the server reads as "not on
414
+ // this bundle" and answers by serving the same bundle again, forever.
415
+ if (!record.identityToken) return;
416
+ if (running === record.identityToken) {
417
+ logger.debug('[OTA] Install verified — running bundle matches what was installed.');
418
+ this.retireIdentityToken(record);
419
+ return;
420
+ }
421
+ logger.error(`[OTA] INSTALL DID NOT TAKE EFFECT — bundle ${this.currentBundle.id} was installed and ` + `carries a known identity marker, but the running bundle reports ` + `${running ?? 'no marker at all'}. The app is executing different code than the slot ` + 'manager believes. Check that the host app resolves the OTA bundle path at launch ' + '(see the ScaleBunOta integration for your React Native version).');
422
+ otaEventEmitter.emitSimple('APPLY_FAILED', this.currentBundle.id, {
423
+ releaseId: this.currentBundle.releaseId,
424
+ error: `install_not_effective — expected ${record.identityToken}, running ${running ?? 'none'}`
425
+ });
426
+ // Deliberately NOT retired: the condition is still true on the next boot and
427
+ // should keep reporting until the integration is fixed. Retiring the token
428
+ // here would make a permanently broken install look like a one-off.
429
+ }
430
+
431
+ // ── Install expectation ────────────────────────────────────────────────────
432
+ // Written just before the restart that activates a bundle, read on the next
433
+ // boot. Synchronous, disk-backed, and the same store used for the device id —
434
+ // it has to survive a process death that happens moments after the write.
435
+
436
+ static INSTALL_EXPECTATION_KEY = 'scalebun.ota.pendingInstall';
437
+ recordInstallExpectation(bundle) {
438
+ try {
439
+ this.storage().set(OtaOrchestrator.INSTALL_EXPECTATION_KEY, JSON.stringify({
440
+ bundleId: bundle.id,
441
+ version: bundle.version,
442
+ // Carried so telemetry emitted on a LATER launch (a boot-guard
443
+ // rollback, an ineffective install) can still be attributed to the
444
+ // release, not merely the bundle. The check response is long gone by
445
+ // then; this record is the only thing that remembers.
446
+ releaseId: bundle.releaseId ?? null,
447
+ // The join key back to the native slot, which records sha256 and
448
+ // nothing else identifying.
449
+ sha256: bundle.sha256,
450
+ identityToken: bundle.identityToken ?? null
451
+ }));
452
+ } catch {
453
+ // Verification is a safety net, never a precondition for installing.
454
+ }
455
+ }
456
+ readInstallRecord() {
457
+ try {
458
+ const raw = this.storage().get(OtaOrchestrator.INSTALL_EXPECTATION_KEY);
459
+ if (!raw) return null;
460
+ const parsed = JSON.parse(raw);
461
+ return typeof parsed?.bundleId === 'string' && typeof parsed?.sha256 === 'string' ? parsed : null;
462
+ } catch {
463
+ return null;
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Drop the identity token once the install has been proven, keeping the rest
469
+ * of the record.
470
+ *
471
+ * The record does two jobs: it proves an install took effect (once), and it
472
+ * maps the native slot's sha256 back to a bundle id (for the life of that
473
+ * bundle). Only the first job is finished after a successful verification, so
474
+ * only the token is retired.
475
+ */
476
+ retireIdentityToken(record) {
477
+ try {
478
+ this.storage().set(OtaOrchestrator.INSTALL_EXPECTATION_KEY, JSON.stringify({
479
+ bundleId: record.bundleId,
480
+ version: record.version,
481
+ releaseId: record.releaseId ?? null,
482
+ sha256: record.sha256,
483
+ identityToken: null
484
+ }));
485
+ } catch {
486
+ /* non-fatal */
487
+ }
488
+ }
489
+ clearInstallExpectation() {
490
+ try {
491
+ this.storage().set(OtaOrchestrator.INSTALL_EXPECTATION_KEY, '');
492
+ } catch {
493
+ /* non-fatal */
494
+ }
495
+ }
496
+ storage() {
497
+ if (!this.storageBackend) this.storageBackend = createStorageBackend();
498
+ return this.storageBackend;
499
+ }
500
+
501
+ /**
502
+ * Sprint 5 (S5-NAT-1): Check if the native boot guard reverted us on this cold start.
503
+ * If getSlotState() shows bootMarkerPresent=false but we have a 'previous' slot
504
+ * and no 'current' OTA bundle, the native layer already reverted.
505
+ */
506
+ checkBootGuardRecovery(state) {
507
+ try {
508
+ if (!state?.bootGuardReverted) return;
509
+
510
+ // WHICH bundle was rolled back, and it has to come from the install
511
+ // record. The obvious source — `state.previous` — is wrong twice over:
512
+ // slot meta.json carries only `{sha256, installedAt}` so it has no bundle
513
+ // id to read, and `revert()` deletes the previous slot as its last step,
514
+ // so by the time this runs there is no previous meta at all. The event
515
+ // therefore reported `bundleId: 'unknown'` on every rollback, and the
516
+ // backend drops any ota_event whose bundleId does not resolve to a bundle
517
+ // the app owns — so the crash-guard's own rollback signal never arrived.
518
+ //
519
+ // Native now stamps the sha256 of the bundle it reverted AWAY FROM into
520
+ // the revert record; the install record maps that back to a bundle id.
521
+ const record = this.readInstallRecord();
522
+ const revertedSha = state.bootGuardRevertedSha256;
523
+ const matchesRecord = !!record && (!revertedSha || record.sha256 === revertedSha);
524
+
525
+ // Report the reason native actually determined — a hash mismatch and a
526
+ // crash loop are different incidents and were being collapsed into one.
527
+ const reason = state.bootGuardRevertReason || 'boot_crash_guard';
528
+ if (matchesRecord && record) {
529
+ logger.warn(`[OTA] Boot guard fired — reverted away from bundle ${record.bundleId} ` + `(v${record.version}); reason: ${reason}`);
530
+ otaEventEmitter.emitSimple('AUTO_ROLLBACK', record.bundleId, {
531
+ releaseId: record.releaseId ?? undefined,
532
+ version: record.version,
533
+ reason
534
+ });
535
+ // The record describes a bundle this device is no longer running.
536
+ this.clearInstallExpectation();
537
+ return;
538
+ }
539
+
540
+ // No usable record (older SDK, cleared storage). Say so rather than
541
+ // emitting an event the server is obliged to discard.
542
+ logger.warn(`[OTA] Boot guard fired (reason: ${reason}) but the rolled-back bundle could not be ` + 'identified locally — no install record. The rollback is not reported to the server.');
543
+ } catch {
544
+ // Slot state parsing failed — non-fatal
545
+ }
546
+ }
547
+ isEnabled() {
548
+ return this.enabled;
549
+ }
550
+
551
+ /**
552
+ * Root/jailbreak indicators detected on this device, as stable reason strings.
553
+ * Empty means nothing was detected — not proof the device is clean.
554
+ */
555
+ deviceIntegrityIndicators() {
556
+ return [...this.integrityIndicators];
557
+ }
558
+
559
+ /**
560
+ * Should this device be refused an update?
561
+ *
562
+ * TRUE only when BOTH are so: the host opted into `'withhold'`, and the native
563
+ * detector actually found something. An empty indicator list is never a reason
564
+ * to withhold — "nothing detected" is the normal state of every healthy
565
+ * device, and treating it as a reason would brick updates for the whole fleet
566
+ * the moment a host set the flag.
567
+ */
568
+ shouldWithhold() {
569
+ // Resolved at DECISION time, not at init: /config is fetched asynchronously,
570
+ // so a policy that arrives mid-session takes effect on the next check rather
571
+ // than only on the next launch.
572
+ //
573
+ // STRICTEST WINS and the server can only TIGHTEN — see
574
+ // resolveCompromisedDevicePolicy. A host that asked for 'withhold' keeps it
575
+ // whatever the server says; a customer who has shipped nothing can still be
576
+ // switched on without an app release, which is the point of the feature.
577
+ return resolveCompromisedDevicePolicy(this.bootGuardConfig.onCompromisedDevice) === 'withhold' && this.integrityIndicators.length > 0;
578
+ }
579
+
580
+ /**
581
+ * Announce the refusal, once per decision point.
582
+ *
583
+ * A withheld update must be visible as a decision, not as an absence. The
584
+ * event carries the indicators that drove it so the host can log WHY, and it
585
+ * names the bundle the device stays on (`'unknown'` for a device still on the
586
+ * factory bundle, which owns no OTA bundle id).
587
+ */
588
+ emitWithheld() {
589
+ logger.warn(`[OTA] Update WITHHELD — device integrity indicators present (${this.integrityIndicators.join(', ')}) ` + "and ota.onCompromisedDevice is 'withhold'. This device stays on its current bundle.");
590
+ otaEventEmitter.emitSimple('UPDATE_WITHHELD', this.currentBundle?.id ?? 'unknown', {
591
+ releaseId: this.currentBundle?.releaseId,
592
+ version: this.currentBundle?.version,
593
+ indicators: [...this.integrityIndicators]
594
+ });
595
+ }
596
+ isRestartRequired() {
597
+ return this.isRestartRequiredState;
598
+ }
599
+
600
+ /**
601
+ * Perform an OTA check against the backend endpoint.
602
+ */
603
+ async checkForUpdate(requestParams) {
604
+ try {
605
+ // ── COMPROMISED-DEVICE POLICY ────────────────────────────────────────
606
+ // Opt-in, default 'allow' (see BootGuardConfig.onCompromisedDevice). The
607
+ // short-circuit is HERE as well as in sync() because checkForUpdate is a
608
+ // public entry point in its own right — the CodePush shim's
609
+ // `checkForUpdate` and any host that drives the check by hand reach the
610
+ // network through this method without going through sync().
611
+ if (this.shouldWithhold()) {
612
+ this.emitWithheld();
613
+ return {
614
+ action: 'NONE'
615
+ };
616
+ }
617
+ const env = this.environment ?? detectOtaEnvironment();
618
+
619
+ // C1: send the channel and targeting context. `channelName` was already an
620
+ // accepted parameter here and was then dropped on the floor — the payload
621
+ // never carried it — so every device resolved to `default` no matter what
622
+ // the host app asked for. Undefined fields are omitted by JSON.stringify,
623
+ // so an app that supplies nothing behaves exactly as before.
624
+ // OTA has no bundle for a non-mobile target; claiming Android there would install the wrong one.
625
+ const mobileOS = resolveMobileOS();
626
+ if (!mobileOS) throw new Error('OTA is not supported on this platform');
627
+ // SDK trust coverage (CICDPAGE §12): report which trusted key IDs are
628
+ // embedded in this binary so the dashboard can measure key-rotation
629
+ // adoption. Telemetry only — the server never trusts a key a device claims.
630
+ // Defensive: optional native method, never let it break a check.
631
+ let trustedKeyIds;
632
+ try {
633
+ const raw = NativeScaleBunOta?.getTrustedKeyIds?.();
634
+ if (raw) {
635
+ const arr = JSON.parse(raw);
636
+ if (Array.isArray(arr) && arr.length) trustedKeyIds = arr.slice(0, 16);
637
+ }
638
+ } catch {
639
+ /* trust reporting is best-effort — never break the update check */
640
+ }
641
+ const payload = {
642
+ appVersion: requestParams.appVersion,
643
+ platform: mobileOS,
644
+ installationId: requestParams.installationId,
645
+ currentBundleId: this.currentBundle?.id,
646
+ currentBundleHash: this.currentBundle?.sha256,
647
+ ...(signedPatchSupported(NativeScaleBunOta) ? {
648
+ otaCapabilities: ['signed_patch_v1']
649
+ } : {}),
650
+ trustedKeyIds,
651
+ // Root/jailbreak indicators, so a console can report how much of a fleet
652
+ // is affected instead of every operator guessing. Telemetry only — the
653
+ // server must never trust it (a rooted device can send `[]`), and the
654
+ // withholding decision above is made entirely on-device.
655
+ //
656
+ // `[]` and absent mean DIFFERENT things and are kept apart: `[]` is
657
+ // "the detector ran and found nothing", absent is "never measured"
658
+ // (native module missing, or the read threw). Sending `[]` for both
659
+ // would report an unmeasured fleet as a clean one.
660
+ integrityIndicators: this.integrityMeasured ? [...this.integrityIndicators] : undefined,
661
+ channelName: requestParams.channelName,
662
+ // Host-supplied country wins; otherwise the cached edge-Worker lookup
663
+ // fills in (see geoCountry.ts). Undefined when neither knows — the
664
+ // server renders unknown as unknown rather than guessing.
665
+ country: requestParams.country ?? getDeviceCountry() ?? undefined,
666
+ // Hardware/OS context under the host's own attributes (host wins on
667
+ // collision) — this is what lets ATTRIBUTE rules target device classes
668
+ // (deviceModel / manufacturer / brand / osVersion / formFactor).
669
+ attributes: {
670
+ ...deviceTargetingAttributes(),
671
+ ...requestParams.attributes
672
+ },
673
+ segmentIds: requestParams.segmentIds,
674
+ lifecycleStage: requestParams.lifecycleStage,
675
+ // Runtime compatibility context. Without these the backend cannot tell
676
+ // whether a bundle is safe for this binary: appVersion is a marketing
677
+ // string, while the RN version and the Hermes bytecode format are the
678
+ // actual runtime contract. A bundle compiled against a different HBC
679
+ // version either fails to load or crashes later on a missing path.
680
+ rnVersion: env.rnVersionString ?? undefined,
681
+ hermes: env.hermes,
682
+ hermesBytecodeVersion: env.hermesBytecodeVersion ?? undefined,
683
+ bridgeless: env.bridgeless
684
+ };
685
+ const url = `${requestParams.apiUrl.replace(/\/+$/, '')}/sdk/ota/check`;
686
+ const data = await retryWithBackoff(async () => {
687
+ const res = await fetch(url, {
688
+ method: 'POST',
689
+ headers: {
690
+ 'Content-Type': 'application/json',
691
+ 'x-scalebun-client-key': requestParams.clientKey
692
+ },
693
+ body: JSON.stringify(payload)
694
+ });
695
+ if (!res.ok) {
696
+ throw new HttpStatusError(`OTA check failed with status ${res.status}`, res.status);
697
+ }
698
+ return await res.json();
699
+ }, {
700
+ label: 'check',
701
+ isRetryable: isRetryableNetworkError
702
+ });
703
+ return data;
704
+ } catch (err) {
705
+ logger.error(`[OTA] checkForUpdate failed: ${err.message}`);
706
+ return {
707
+ action: 'NONE'
708
+ };
709
+ }
710
+ }
711
+
712
+ /**
713
+ * Downloads, stage, and apply an update in one step.
714
+ * Sprint 5: emits lifecycle events + starts boot-guard heartbeat.
715
+ */
716
+ /**
717
+ * Minimum gap between network checks. Not a policy, a stampede guard: an
718
+ * app that syncs on mount AND on every foreground transition can otherwise
719
+ * issue a burst of identical checks. Small enough not to get in the way of
720
+ * publishing and testing a release.
721
+ */
722
+ static MIN_CHECK_INTERVAL_MS = 15_000;
723
+
724
+ /**
725
+ * Check, download, stage and apply — at most ONE at a time.
726
+ *
727
+ * Concurrent callers join the sync already running rather than starting a
728
+ * second one, and a call made while an update is already staged returns
729
+ * without touching the slots: the staged bundle has to be activated by a
730
+ * restart before anything else can usefully happen, and re-checking here
731
+ * is what used to chain a second install onto the first.
732
+ */
733
+ async sync(rawParams) {
734
+ if (this.isRestartRequiredState) {
735
+ logger.debug('[OTA] An update is staged and waiting for a restart — skipping this check.');
736
+ return {
737
+ status: 'UP_TO_DATE',
738
+ bundle: this.pendingBundle ?? undefined
739
+ };
740
+ }
741
+ if (this.syncInFlight) {
742
+ logger.debug('[OTA] A sync is already running — joining it.');
743
+ return this.syncInFlight;
744
+ }
745
+ const elapsed = Date.now() - this.lastCheckAt;
746
+ if (this.lastCheckAt > 0 && elapsed < OtaOrchestrator.MIN_CHECK_INTERVAL_MS) {
747
+ logger.debug(`[OTA] Checked ${Math.round(elapsed / 1000)}s ago — within the ${OtaOrchestrator.MIN_CHECK_INTERVAL_MS / 1000}s minimum interval, skipping.`);
748
+ return {
749
+ status: 'UP_TO_DATE'
750
+ };
751
+ }
752
+ this.lastCheckAt = Date.now();
753
+ this.syncInFlight = this.runSync(rawParams).finally(() => {
754
+ this.syncInFlight = null;
755
+ });
756
+ return this.syncInFlight;
757
+ }
758
+ async runSync(rawParams) {
759
+ const params = {
760
+ ...rawParams,
761
+ installationId: rawParams.installationId ?? resolveInstallationId(),
762
+ // ENFORCED GLOBALLY: the legacy client `autoRestart` override is ignored —
763
+ // pinned false here so no app config (or future code path that reads
764
+ // params.autoRestart) can re-enable it. Activation is driven STRICTLY by
765
+ // the release's server-set installMode: IMMEDIATE restarts now,
766
+ // ON_NEXT_RESUME arms a resume-restart, ON_NEXT_RESTART (default) applies
767
+ // on the next cold start. Honouring `autoRestart:true` forced every release
768
+ // to restart immediately (defeating installMode), and on bridgeless it
769
+ // forced the in-process restart that cannot load a staged bundle.
770
+ autoRestart: false
771
+ };
772
+ try {
773
+ if (!this.enabled || !NativeScaleBunOta) {
774
+ return {
775
+ status: 'ERROR',
776
+ error: 'OTA native module disabled or missing'
777
+ };
778
+ }
779
+
780
+ // ── COMPROMISED-DEVICE POLICY ────────────────────────────────────────
781
+ // Before ANY network call and before the CHECK event: a withheld device
782
+ // must not appear in the funnel's denominator as a device that asked and
783
+ // was told nothing. It did not ask. Default is 'allow', so this is inert
784
+ // unless the host opted in (see BootGuardConfig.onCompromisedDevice).
785
+ if (this.shouldWithhold()) {
786
+ this.emitWithheld();
787
+ return {
788
+ status: 'WITHHELD'
789
+ };
790
+ }
791
+ logger.debug('[OTA] Sync started…');
792
+
793
+ // The funnel's denominator, for devices already on an OTA bundle. Emitted
794
+ // before the request, so a check that fails outright still counts as a
795
+ // check — the only CHECK rows before this came from a server-side geo
796
+ // side-effect that is skipped whenever the request carries no country.
797
+ //
798
+ // Only when a current bundle is known: every ota_event must name a bundle
799
+ // the app owns or the server drops it, and a device still on the binary's
800
+ // factory bundle has no such id to give. Those devices are counted
801
+ // server-side when they are offered something.
802
+ if (this.currentBundle?.id) {
803
+ otaEventEmitter.emitSimple('CHECK', this.currentBundle.id, {
804
+ releaseId: this.currentBundle.releaseId,
805
+ version: this.currentBundle.version
806
+ });
807
+ }
808
+ const checkRes = await this.checkForUpdate(params);
809
+ if (checkRes.action === 'NONE') {
810
+ logger.debug('[OTA] App is up to date');
811
+ // If we booted from an OTA bundle and it's healthy, clear the boot guard
812
+ this.startBootGuardHeartbeat();
813
+ return {
814
+ status: 'UP_TO_DATE'
815
+ };
816
+ }
817
+
818
+ // Handle server-initiated rollback (Sprint 4)
819
+ if (checkRes.action === 'ROLLBACK') {
820
+ logger.warn('[OTA] Server requested ROLLBACK — reverting to previous bundle');
821
+ otaEventEmitter.emitSimple('MANUAL_ROLLBACK', this.currentBundle?.id ?? 'unknown', {
822
+ releaseId: this.currentBundle?.releaseId
823
+ });
824
+ const reverted = await NativeScaleBunOta.revertToPrevious();
825
+ if (reverted) {
826
+ this.currentBundle = null;
827
+ // isRestartRequired flips true; the reverted bundle binds on the next
828
+ // cold start. autoRestart is intentionally not consulted (pinned false
829
+ // in sync()) — activation policy is uniform across update and rollback.
830
+ this.isRestartRequiredState = true;
831
+ return {
832
+ status: 'ROLLED_BACK'
833
+ };
834
+ }
835
+ return {
836
+ status: 'ERROR',
837
+ error: 'Native rollback failed'
838
+ };
839
+ }
840
+ if (!checkRes.bundle) {
841
+ return {
842
+ status: 'UP_TO_DATE'
843
+ };
844
+ }
845
+ const bundle = checkRes.bundle;
846
+ // When the presigned download URL (300 s TTL) was issued — a retry past 240 s re-checks.
847
+ const offeredAt = Date.now();
848
+ let patchUsed = false;
849
+
850
+ // The offer itself. Everything downstream (download, install, activation)
851
+ // is a conversion against this, so without it the top of the funnel was
852
+ // unmeasurable and a rollout that never reached devices looked identical
853
+ // to one whose devices all declined to download.
854
+ otaEventEmitter.emitSimple('OFFERED', bundle.id, {
855
+ releaseId: bundle.releaseId,
856
+ version: bundle.version
857
+ });
858
+
859
+ // ── DOWNLOAD ─────────────────────────────────────────────────────────
860
+ // Authenticity is enforced NATIVELY now (see the envelope branch below):
861
+ // SHA-256 proves the bytes arrived intact, and for signed releases the
862
+ // RSA signature — checked in native code against keys embedded in the app
863
+ // package — proves they came from you. JS neither pins keys nor verifies
864
+ // signatures.
865
+ otaEventEmitter.emitSimple('DOWNLOAD_STARTED', bundle.id, {
866
+ releaseId: bundle.releaseId,
867
+ version: bundle.version
868
+ });
869
+ const downloadStart = Date.now();
870
+ logger.debug(`[OTA] Downloading update v${bundle.version}…`);
871
+
872
+ // Live progress: native tick → DOWNLOAD_PROGRESS (feeds useOtaUpdate) →
873
+ // throttled POST to the live tracker. `bundle.size` is the authoritative
874
+ // total — the server just told us — so an unknown native total (-1 on
875
+ // chunked/gzip bodies) still yields a truthful percentage.
876
+ let lastPostAt = 0;
877
+ const postProgress = (bytesRead, status) => {
878
+ const total = bundle.size > 0 ? bundle.size : Math.max(bytesRead, 1);
879
+ const percent = Math.min(100, Math.round(bytesRead / total * 100));
880
+ const elapsedS = (Date.now() - downloadStart) / 1000;
881
+ const payload = {
882
+ installationId: params.installationId,
883
+ bundleId: bundle.id,
884
+ bytesRead,
885
+ totalBytes: total,
886
+ progressPercent: percent,
887
+ speedKbps: elapsedS > 0 ? Math.round(bytesRead / 1024 / elapsedS) : 0,
888
+ status
889
+ };
890
+ // Fire-and-forget: progress display must never delay or fail the
891
+ // download it describes.
892
+ fetch(`${params.apiUrl.replace(/\/+$/, '')}/sdk/ota/progress`, {
893
+ method: 'POST',
894
+ headers: {
895
+ 'Content-Type': 'application/json',
896
+ 'x-scalebun-client-key': params.clientKey
897
+ },
898
+ body: JSON.stringify(payload)
899
+ }).catch(() => {});
900
+ };
901
+ const unsubscribeProgress = subscribeNativeProgress(({
902
+ bytesRead
903
+ }) => {
904
+ const total = bundle.size > 0 ? bundle.size : bytesRead;
905
+ otaEventEmitter.emit({
906
+ type: 'DOWNLOAD_PROGRESS',
907
+ bundleId: bundle.id,
908
+ timestamp: Date.now(),
909
+ progress: Math.min(100, Math.round(bytesRead / Math.max(total, 1) * 100))
910
+ });
911
+ const now = Date.now();
912
+ if (now - lastPostAt >= PROGRESS_POST_INTERVAL_MS) {
913
+ lastPostAt = now;
914
+ postProgress(bytesRead, 'DOWNLOADING');
915
+ }
916
+ });
917
+ let staged = false;
918
+ if (bundle.envelope) {
919
+ // ── NATIVE-ENFORCED VERIFY + STAGE (SB-OTA-RSA-SHA256-V1) ───────────
920
+ // Hand the whole envelope to native code, which verifies the RSA
921
+ // signature against the keys EMBEDDED in the app package, then downloads
922
+ // the artifact, enforces the SIGNED size + SHA-256, and stages it into
923
+ // the `next` slot — all outside JS. JavaScript never stages bytes it has
924
+ // not proven authentic. No patch path here: a signed offer is always a
925
+ // full verified download (native patch is a documented follow-up).
926
+ //
927
+ // Retried when — and only when — a retry can help (see signedDownload.ts): one dropped
928
+ // connection used to lose a 19 MB update until the next cold start. A retry after an
929
+ // expired URL asks the server again, and stops quietly if the release was withdrawn.
930
+ const native = NativeScaleBunOta;
931
+
932
+ // Patch FIRST when the server offered one and this binary can apply it signed. One
933
+ // attempt, no retry: on any failure the full download below runs exactly as before, so a
934
+ // patch can only ever save bytes. Security lives in native (verifyAndStagePatch): the
935
+ // rebuilt bundle must hash to the SIGNED artifactSha256, from a signed base.
936
+ if (bundle.patch && signedPatchSupported(native)) {
937
+ const pv = await trySignedPatch(native, bundle.envelope, bundle.url, bundle.patch);
938
+ if (pv.ok) {
939
+ patchUsed = true;
940
+ staged = true;
941
+ logger.debug(`[OTA] Staged v${bundle.version} from a ${(bundle.patch.size / 1024).toFixed(0)} KB patch`);
942
+ } else {
943
+ logger.info(`[OTA] Patch not applied (${pv.code ?? "unknown"}) — downloading the full bundle`);
944
+ }
945
+ }
946
+ if (!staged) {
947
+ const result = await stageSignedWithRetry({
948
+ attempt: async b => {
949
+ try {
950
+ const verdictJson = await native.verifyAndStageRelease(JSON.stringify({
951
+ ...b.envelope,
952
+ downloadUrl: b.url
953
+ }));
954
+ return JSON.parse(verdictJson);
955
+ } catch (err) {
956
+ // A rejected promise (or an unparseable verdict) is machinery failure,
957
+ // never a valid result — treat it as a hard failure (not retried).
958
+ return {
959
+ ok: false,
960
+ code: 'verify_stage_threw',
961
+ message: err?.message ?? String(err)
962
+ };
963
+ }
964
+ },
965
+ recheck: async () => {
966
+ const again = await this.checkForUpdate(params);
967
+ return again.action === 'DOWNLOAD' && again.bundle?.envelope ? again.bundle : null;
968
+ },
969
+ now: () => Date.now(),
970
+ sleep: ms => new Promise(r => setTimeout(r, ms))
971
+ }, bundle, offeredAt);
972
+ const verdict = result.verdict;
973
+ if (result.withdrawn) {
974
+ unsubscribeProgress();
975
+ // No progress post: the live tracker's vocabulary has no "withdrawn", and FAILED would
976
+ // report a release the server stopped offering as a device that failed to download it.
977
+ logger.info(`[OTA] Release v${bundle.version} is no longer offered — stopping the download without reporting a failure.`);
978
+ return {
979
+ status: 'UP_TO_DATE'
980
+ };
981
+ }
982
+ if (!verdict.ok) {
983
+ unsubscribeProgress();
984
+ postProgress(0, 'FAILED');
985
+ logger.error(`[OTA] Native verify/stage refused the release: ${verdict.code ?? 'unknown'}` + `${verdict.message ? ` — ${verdict.message}` : ''}`);
986
+ otaEventEmitter.emitSimple('APPLY_FAILED', bundle.id, {
987
+ releaseId: bundle.releaseId,
988
+ // `error` is mapped onto the wire `errorCode` by deliverOtaEvents —
989
+ // carry the stable native verdict code there, with the download
990
+ // reason when native gave one from the fixed vocabulary
991
+ // (`DOWNLOAD_FAILED:http_403`). Emitted ONCE, after the last attempt.
992
+ error: verdictErrorCode(verdict),
993
+ version: bundle.version
994
+ });
995
+ return {
996
+ status: 'ERROR',
997
+ error: `Release verification failed (${verdict.code ?? 'unknown'})`,
998
+ bundle
999
+ };
1000
+ }
1001
+ staged = true;
1002
+ }
1003
+ } else {
1004
+ // ── LEGACY / UNSIGNED (SHA-256 integrity only) ─────────────────────
1005
+ // No envelope means the app embeds no trusted keys and the release is
1006
+ // unsigned: keep the pre-RSA behaviour so those apps still update.
1007
+
1008
+ // Sprint 7: Try patch first if offered, fall back to full bundle
1009
+ if (bundle.patch && NativeScaleBunOta.stagePatch) {
1010
+ logger.debug(`[OTA] Patch available (${(bundle.patch.size / 1024).toFixed(0)} KB vs ` + `${(bundle.size / 1024).toFixed(0)} KB full) — trying patch…`);
1011
+ try {
1012
+ staged = await NativeScaleBunOta.stagePatch(bundle.patch.url, bundle.patch.sha256, bundle.sha256 // expected full-bundle hash after patching
1013
+ );
1014
+ if (staged) {
1015
+ patchUsed = true;
1016
+ logger.debug('[OTA] Patch applied successfully');
1017
+ } else {
1018
+ logger.warn('[OTA] Patch staging returned false — falling back to full bundle');
1019
+ }
1020
+ } catch (patchErr) {
1021
+ logger.warn(`[OTA] Patch staging failed: ${patchErr.message} — falling back to full bundle`);
1022
+ }
1023
+ }
1024
+
1025
+ // Full-bundle fallback (or primary path when no patch is available).
1026
+ // Retried with backoff: on a mobile network a transient drop mid-download
1027
+ // is the common case, and previously one failure meant waiting for the
1028
+ // next cold start — often hours away, sometimes never.
1029
+ if (!staged) {
1030
+ try {
1031
+ staged = await retryWithBackoff(async () => {
1032
+ const ok = await NativeScaleBunOta.stageBundle(bundle.url, bundle.sha256);
1033
+ if (!ok) {
1034
+ // Native returns a bare boolean, so a hash mismatch and a
1035
+ // dropped connection are indistinguishable here. Retrying a
1036
+ // genuine mismatch a couple of times is cheap; not retrying a
1037
+ // dropped connection costs the whole update.
1038
+ throw new Error('stageBundle returned false');
1039
+ }
1040
+ return ok;
1041
+ }, {
1042
+ label: `download v${bundle.version}`,
1043
+ attempts: 3
1044
+ });
1045
+ } catch {
1046
+ staged = false;
1047
+ }
1048
+ }
1049
+ }
1050
+ unsubscribeProgress();
1051
+ if (!staged) {
1052
+ postProgress(0, 'FAILED');
1053
+ logger.error('[OTA] Staging bundle failed after retries');
1054
+ otaEventEmitter.emitSimple('APPLY_FAILED', bundle.id, {
1055
+ releaseId: bundle.releaseId,
1056
+ error: 'Staging failed — SHA-256 mismatch or download error',
1057
+ version: bundle.version
1058
+ });
1059
+ return {
1060
+ status: 'ERROR',
1061
+ error: 'Staging bundle failed',
1062
+ bundle
1063
+ };
1064
+ }
1065
+ postProgress(bundle.size, 'COMPLETED');
1066
+ const downloadDuration = Date.now() - downloadStart;
1067
+ otaEventEmitter.emitSimple('DOWNLOAD_COMPLETE', bundle.id, {
1068
+ releaseId: bundle.releaseId,
1069
+ version: bundle.version,
1070
+ durationMs: downloadDuration,
1071
+ patchUsed
1072
+ });
1073
+
1074
+ // ── APPLY ────────────────────────────────────────────────────────────
1075
+ // 2. Apply update atomically (next→current, current→previous, sets boot marker)
1076
+ const applied = await NativeScaleBunOta.applyUpdate();
1077
+ if (!applied) {
1078
+ logger.error('[OTA] Applying update failed');
1079
+ otaEventEmitter.emitSimple('APPLY_FAILED', bundle.id, {
1080
+ releaseId: bundle.releaseId,
1081
+ error: 'Atomic slot swap failed',
1082
+ version: bundle.version
1083
+ });
1084
+ return {
1085
+ status: 'ERROR',
1086
+ error: 'Applying update failed',
1087
+ bundle
1088
+ };
1089
+ }
1090
+
1091
+ // NOT `this.currentBundle` — see the field docs. This process is still
1092
+ // executing the previous bundle; the staged one becomes current when a
1093
+ // restart binds it, and hydrateCurrentBundleFromSlots reads it back from
1094
+ // the install record on the next launch.
1095
+ this.pendingBundle = bundle;
1096
+ this.isRestartRequiredState = true;
1097
+
1098
+ // Written BEFORE the restart, so the next boot can prove whether this
1099
+ // install actually took effect. Only recorded when the server told us the
1100
+ // bundle carries a marker — otherwise there is nothing to compare against
1101
+ // and a recorded expectation would produce a false alarm.
1102
+ // Recorded unconditionally, not only when a marker is present: this is
1103
+ // also the record that tells the next launch WHICH bundle the slot's
1104
+ // sha256 belongs to, without which the device cannot report what it is
1105
+ // running. Identity verification is the second job of this record, and
1106
+ // it is skipped when there is no marker to compare.
1107
+ this.recordInstallExpectation(bundle);
1108
+ otaEventEmitter.emitSimple('INSTALLED', bundle.id, {
1109
+ releaseId: bundle.releaseId,
1110
+ version: bundle.version
1111
+ });
1112
+ logger.debug(`[OTA] Update v${bundle.version} installed successfully!`);
1113
+
1114
+ // Deliver telemetry BEFORE a restart tears the JS runtime down —
1115
+ // an INSTALLED event queued but not sent would vanish with the process.
1116
+ await deliverOtaEvents(params);
1117
+
1118
+ // Activation is driven STRICTLY by the release's installMode. The legacy
1119
+ // client `autoRestart` override is pinned false in sync() (see above), so
1120
+ // it no longer participates — a release activates exactly as published:
1121
+ // IMMEDIATE restarts now, ON_NEXT_RESUME on next foreground, and
1122
+ // ON_NEXT_RESTART (the default) on the next cold start.
1123
+ const installMode = bundle.installMode ?? 'ON_NEXT_RESTART';
1124
+ if (installMode === 'IMMEDIATE') {
1125
+ this.restart();
1126
+ } else if (installMode === 'ON_NEXT_RESUME') {
1127
+ this.armResumeRestart();
1128
+ }
1129
+ return {
1130
+ status: 'UPDATE_INSTALLED',
1131
+ bundle,
1132
+ isMandatory: bundle.isMandatory
1133
+ };
1134
+ } catch (err) {
1135
+ logger.error(`[OTA] Sync error: ${err.message}`);
1136
+ return {
1137
+ status: 'ERROR',
1138
+ error: err.message ?? 'Unexpected sync failure'
1139
+ };
1140
+ } finally {
1141
+ // Every other exit (UP_TO_DATE, ROLLBACK, staging failure, throw)
1142
+ // delivers here. This also carries events queued at INIT — boot-guard
1143
+ // AUTO_ROLLBACKs and identity-check APPLY_FAILEDs fire before any
1144
+ // apiUrl/clientKey exist, so they wait in the queue for the first sync.
1145
+ // Fire-and-forget: delivery is never allowed to delay a result.
1146
+ void deliverOtaEvents(params);
1147
+ }
1148
+ }
1149
+
1150
+ /**
1151
+ * Sprint 5 (S5-NAT-1): Boot-guard heartbeat.
1152
+ *
1153
+ * After booting from an OTA bundle, start a timer. If the app survives
1154
+ * `healthyAfterMs` without crashing, call `markHealthy()` to clear the
1155
+ * native boot-guard marker. If JS crashes before the timer fires, the
1156
+ * marker stays set and native code reverts on next cold start.
1157
+ */
1158
+ startBootGuardHeartbeat(preRead) {
1159
+ if (!NativeScaleBunOta) return;
1160
+ // A render error already condemned this launch; nothing may re-arm the heartbeat.
1161
+ if (this.bootFailedThisLaunch) return;
1162
+
1163
+ // Cancel any existing timer
1164
+ if (this.healthyTimer) {
1165
+ clearTimeout(this.healthyTimer);
1166
+ this.healthyTimer = null;
1167
+ }
1168
+ try {
1169
+ // getSlotState() is CONSUME-ON-READ for the revert record, so a caller that
1170
+ // has already read it passes the parsed result down rather than letting
1171
+ // this read again and swallow a rollback. `null` is a real answer (module
1172
+ // absent or payload unreadable) — only `undefined` means "nobody read it".
1173
+ const state = preRead !== undefined ? preRead : JSON.parse(NativeScaleBunOta.getSlotState());
1174
+
1175
+ // Only run the heartbeat if boot-guard marker is present
1176
+ // (meaning we're running from a freshly-applied OTA bundle)
1177
+ if (!state?.bootMarkerPresent) {
1178
+ return;
1179
+ }
1180
+ const healthyMs = this.bootGuardConfig.healthyAfterMs ?? DEFAULT_HEALTHY_AFTER_MS;
1181
+ logger.debug(`[OTA] Boot guard active — marking healthy after ${healthyMs}ms`);
1182
+ this.healthyTimer = setTimeout(() => {
1183
+ noThrow(() => {
1184
+ NativeScaleBunOta?.markHealthy();
1185
+ logger.info('[OTA] Boot guard cleared — bundle marked healthy ✓');
1186
+ this.healthyTimer = null;
1187
+
1188
+ // The honest activation signal. INSTALLED is emitted optimistically,
1189
+ // BEFORE the bundle has ever executed, so counting it as adoption
1190
+ // credits bundles that were installed and then crash-reverted. This
1191
+ // fires only once the bundle has actually booted and survived.
1192
+ const running = this.currentBundle;
1193
+ if (running?.id) {
1194
+ otaEventEmitter.emitSimple('BOOT_SUCCESS', running.id, {
1195
+ releaseId: running.releaseId,
1196
+ version: running.version,
1197
+ durationMs: healthyMs
1198
+ });
1199
+ }
1200
+ });
1201
+ }, healthyMs);
1202
+ } catch {
1203
+ // State parsing failed — non-fatal, don't block
1204
+ }
1205
+ }
1206
+ bootFailedThisLaunch = false;
1207
+
1208
+ /**
1209
+ * A render error was caught while a freshly-applied bundle is still inside its health window.
1210
+ *
1211
+ * WHY. The boot guard's only evidence of a bad bundle is that the process died before
1212
+ * `healthyAfterMs`. An error boundary with a fallback keeps the process ALIVE: the user sees the
1213
+ * fallback, the timer fires, `markHealthy()` runs, and a bundle that cannot render its first
1214
+ * screen is recorded as healthy and never reverted. ScaleBunErrorBoundary calls this so the
1215
+ * marker stays set: the next cold start counts toward the bundle's revert exactly as a crash
1216
+ * would have.
1217
+ *
1218
+ * No-op outside the window (the bundle already proved itself, or this launch is not an OTA
1219
+ * bundle's first run), so a boundary catching an ordinary bug later in the session never
1220
+ * condemns a healthy release.
1221
+ *
1222
+ * @returns true when the window was open and `markHealthy` has been withheld.
1223
+ */
1224
+ noteBootFailure() {
1225
+ if (!this.healthyTimer) return false;
1226
+ clearTimeout(this.healthyTimer);
1227
+ this.healthyTimer = null;
1228
+ this.bootFailedThisLaunch = true;
1229
+ logger.warn('[OTA] Boot guard: a render error was caught inside the health window — this bundle is NOT ' + 'marked healthy, and the next cold start counts toward reverting it.');
1230
+ return true;
1231
+ }
1232
+
1233
+ /** One-shot guard so repeated syncs cannot stack resume listeners. */
1234
+ resumeRestartArmed = false;
1235
+
1236
+ /**
1237
+ * ON_NEXT_RESUME: restart the JS runtime the next time the app returns to
1238
+ * the foreground after genuinely being in the background.
1239
+ *
1240
+ * The staged bundle is already applied at this point — the restart is purely
1241
+ * about WHEN the user experiences the reload. Two deliberate choices:
1242
+ *
1243
+ * - Armed only after a real background→active transition, never on the
1244
+ * initial 'active' state, so installing while the user is mid-session
1245
+ * does not instantly yank the screen out from under them.
1246
+ * - One-shot. The listener removes itself after firing (or after the
1247
+ * restart makes the whole question moot).
1248
+ */
1249
+ armResumeRestart() {
1250
+ if (this.resumeRestartArmed) return;
1251
+ this.resumeRestartArmed = true;
1252
+ let wasBackground = false;
1253
+ try {
1254
+ const sub = AppState.addEventListener('change', state => {
1255
+ if (state === 'background') {
1256
+ wasBackground = true;
1257
+ return;
1258
+ }
1259
+ if (state === 'active' && wasBackground) {
1260
+ try {
1261
+ sub.remove();
1262
+ } catch {
1263
+ /* the restart below makes cleanup moot */
1264
+ }
1265
+ this.resumeRestartArmed = false;
1266
+ logger.info('[OTA] App resumed — activating the staged update now');
1267
+ this.restart();
1268
+ }
1269
+ });
1270
+ logger.debug('[OTA] Update staged — will activate on next resume (ON_NEXT_RESUME)');
1271
+ } catch {
1272
+ // AppState unavailable (tests, exotic hosts): the update still activates
1273
+ // on the next cold start, which is the documented fallback behaviour.
1274
+ this.resumeRestartArmed = false;
1275
+ }
1276
+ }
1277
+
1278
+ /**
1279
+ * Reload the JS app bundle to apply the new update immediately.
1280
+ *
1281
+ * Order matters: the native `restartApp()` is the only path that works in
1282
+ * RELEASE builds. `DevSettings.reload()` looks callable there too — it
1283
+ * logged, returned, and reloaded nothing when tested live on a release APK,
1284
+ * which made every "restart" this SDK ever promised a silent no-op in
1285
+ * production. DevSettings remains as the dev-build fallback for hosts that
1286
+ * have not rebuilt native yet.
1287
+ */
1288
+ restart() {
1289
+ noThrow(() => {
1290
+ logger.info('[OTA] Triggering app restart…');
1291
+ if (NativeScaleBunOta && typeof NativeScaleBunOta.restartApp === 'function') {
1292
+ NativeScaleBunOta.restartApp();
1293
+ } else if (DevSettings && typeof DevSettings.reload === 'function') {
1294
+ DevSettings.reload();
1295
+ } else if (NativeModules.RNReload) {
1296
+ NativeModules.RNReload.reload();
1297
+ }
1298
+ });
1299
+ }
1300
+ }
1301
+ export const otaOrchestrator = new OtaOrchestrator();
1302
+ //# sourceMappingURL=OtaOrchestrator.js.map