@xenon-device-management/xenon 2.14.0 → 2.16.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 (335) hide show
  1. package/README.md +44 -29
  2. package/lib/package.json +6 -5
  3. package/lib/public/assets/{AnnotationOverlay-B_VNtKBH.js → AnnotationOverlay-2W4JvEyZ.js} +1 -1
  4. package/lib/public/assets/{ApiKeyGate-BwuaMjkX.js → ApiKeyGate-GmckX_7r.js} +1 -1
  5. package/lib/public/assets/DeviceMosaicView-DqODzkyo.js +2 -0
  6. package/lib/public/assets/{EmptyState-BSjhk_IV.js → EmptyState-7hETKEWb.js} +1 -1
  7. package/lib/public/assets/{FieldGroup-Cb5QZsE1.js → FieldGroup-GOgssFEP.js} +1 -1
  8. package/lib/public/assets/{FilterMenu-BAaSlWbW.js → FilterMenu-Yvf6RGMd.js} +1 -1
  9. package/lib/public/assets/{Menu-JGGYrSQQ.js → Menu-KrPnfdsf.js} +1 -1
  10. package/lib/public/assets/{Modal-CFCp3n9d.js → Modal-C6WjZFeI.js} +1 -1
  11. package/lib/public/assets/{RecordingPage-CbJj_EBT.js → RecordingPage-CSRIhZEh.js} +1 -1
  12. package/lib/public/assets/{RecordingsPage-BJeYnygR.js → RecordingsPage-CB8ST3nE.js} +1 -1
  13. package/lib/public/assets/{SegmentedControl-Bg42Atjy.js → SegmentedControl-C9o90KId.js} +1 -1
  14. package/lib/public/assets/{SettingCard-Njz1pUIJ.js → SettingCard-CPm3w9l2.js} +1 -1
  15. package/lib/public/assets/{Table-BcTm5xV2.js → Table-DwIgERRt.js} +1 -1
  16. package/lib/public/assets/{activity-DOVdsfMQ.js → activity-DrLbHifn.js} +1 -1
  17. package/lib/public/assets/ai-settings-DU_Ls06P.js +16 -0
  18. package/lib/public/assets/{api-keys-BKnNSTw9.js → api-keys-CWYdEzJ_.js} +1 -1
  19. package/lib/public/assets/{apps-D0SC6uw6.js → apps-BqNVdln7.js} +1 -1
  20. package/lib/public/assets/{arrow-left-MMbTmgoE.js → arrow-left-BtB0_Jg_.js} +1 -1
  21. package/lib/public/assets/{arrow-right-BMfnGmxW.js → arrow-right-C8NhdtyN.js} +1 -1
  22. package/lib/public/assets/{arrow-up-right-DuAftMWB.js → arrow-up-right-gMg0ffvv.js} +1 -1
  23. package/lib/public/assets/{auth-shell-nZC2JNDO.js → auth-shell-CiYZ3N4M.js} +2 -2
  24. package/lib/public/assets/{builds-page-hDCgTwkS.js → builds-page-EaaqDmLN.js} +1 -1
  25. package/lib/public/assets/{button-Dda4irn_.js → button-DDau4Axv.js} +1 -1
  26. package/lib/public/assets/{calendar-BMr0Q62v.js → calendar-DQ83B1ed.js} +1 -1
  27. package/lib/public/assets/{check-CZ9iw9-e.js → check-K1ovTQam.js} +1 -1
  28. package/lib/public/assets/{chevron-right-BRYJJVC9.js → chevron-right-Biq00pMt.js} +1 -1
  29. package/lib/public/assets/{circle-check-CqAJjQ5O.js → circle-check-CBv88cH7.js} +1 -1
  30. package/lib/public/assets/{circle-x-DlDJtnVz.js → circle-x-Bmltailn.js} +1 -1
  31. package/lib/public/assets/{clock-CpuDKysU.js → clock-BPrld-3h.js} +1 -1
  32. package/lib/public/assets/{copy-CAQydNFe.js → copy-t0QB14JI.js} +1 -1
  33. package/lib/public/assets/derive-UnLRp4r3.js +1 -0
  34. package/lib/public/assets/device-explorer-BgGZ8AvV.js +282 -0
  35. package/lib/public/assets/{download-C9XG6lLv.js → download-BroHxNOh.js} +1 -1
  36. package/lib/public/assets/forgot-password-Bjmf49i6.js +1 -0
  37. package/lib/public/assets/{h264Stream-VQBphYhg.js → h264Stream-DeD__6wa.js} +6 -6
  38. package/lib/public/assets/{index-DJGc1M2f.js → index-72oF89LJ.js} +1 -1
  39. package/lib/public/assets/index-B0JeuZbg.js +15 -0
  40. package/lib/public/assets/index-B0gQkEg0.js +219 -0
  41. package/lib/public/assets/{input-Cm0tmSoc.js → input-DIc4MSC7.js} +1 -1
  42. package/lib/public/assets/{line-chart-D2DyJCml.js → line-chart-BcWm2vW8.js} +1 -1
  43. package/lib/public/assets/{list-checks-UWf1GY99.js → list-checks-B06IJJad.js} +1 -1
  44. package/lib/public/assets/{lock-CCJv9m_I.js → lock-pVLvnN30.js} +1 -1
  45. package/lib/public/assets/{login-f8vOVW-U.js → login-CN77vy--.js} +1 -1
  46. package/lib/public/assets/{maintenance-settings-C1PrkuAH.js → maintenance-settings-CSdzQSkY.js} +1 -1
  47. package/lib/public/assets/{monitor-B2jDgwm7.js → monitor-BtrN5IkI.js} +1 -1
  48. package/lib/public/assets/{mouse-pointer-2-DLI1RtzU.js → mouse-pointer-2-CNsQfo6w.js} +1 -1
  49. package/lib/public/assets/{network-ebT86qoi.js → network-BSfA8ZxG.js} +1 -1
  50. package/lib/public/assets/{overview-C0aykVrd.js → overview-BfTebCK5.js} +1 -1
  51. package/lib/public/assets/{page-header-BjzgWz-T.js → page-header-D8KUX6Qg.js} +1 -1
  52. package/lib/public/assets/{play-DLG9t8FU.js → play-Cvc8xzic.js} +1 -1
  53. package/lib/public/assets/{plus-nBFSMu_X.js → plus-C9Zj84UF.js} +1 -1
  54. package/lib/public/assets/{profile-page-CSl0UYlv.js → profile-page-Bi27STgs.js} +1 -1
  55. package/lib/public/assets/{reset-password-LeOuHqmB.js → reset-password-CPsOuwSu.js} +1 -1
  56. package/lib/public/assets/runbook-page-DEQ-DBOX.js +304 -0
  57. package/lib/public/assets/{select-88jHcl-Z.js → select-BWpnhWXj.js} +1 -1
  58. package/lib/public/assets/{selector-detail-redirect-BbXKJjZM.js → selector-detail-redirect-BefSCSpe.js} +1 -1
  59. package/lib/public/assets/{selector-health-page-B4rA1Xkv.js → selector-health-page-MSk96Zz7.js} +1 -1
  60. package/lib/public/assets/session-detail-page-DPyBNef_.js +4 -0
  61. package/lib/public/assets/{settings-Dep_3kbA.css → settings-K8UHWMdI.css} +1 -1
  62. package/lib/public/assets/{settings-GF6ZMSQ6.js → settings-V6x-cXwy.js} +1 -1
  63. package/lib/public/assets/{stat-tile-BV98e_Sv.js → stat-tile-Duex-GZD.js} +1 -1
  64. package/lib/public/assets/{tablet-BiAsnFDj.js → tablet-BBcoqBmL.js} +1 -1
  65. package/lib/public/assets/{teams-B4-jrr-1.js → teams-ts8p5rEh.js} +1 -1
  66. package/lib/public/assets/{trash-2-C5RSuX0e.js → trash-2-CZ2ew6AZ.js} +1 -1
  67. package/lib/public/assets/{upload-BG7_rMXK.js → upload-Dv99y_le.js} +1 -1
  68. package/lib/public/assets/{use-builds-data-J-riQYyC.js → use-builds-data-DrYC8JCF.js} +1 -1
  69. package/lib/public/assets/{use-password-reset-mode-C8-eH-UG.js → use-password-reset-mode-C7QkBNkP.js} +1 -1
  70. package/lib/public/assets/{users-CFba5TSy.js → users-D7tKMESH.js} +1 -1
  71. package/lib/public/assets/{users-Cp0beJm3.js → users-gJ5Y01yo.js} +1 -1
  72. package/lib/public/assets/{video-off-DDsEISjV.js → video-off-CqZVuZGs.js} +1 -1
  73. package/lib/public/assets/{webhook-settings-BGu32vSB.js → webhook-settings-DI5DSW99.js} +1 -1
  74. package/lib/public/assets/{zap-l4VaXzq8.js → zap-ClcHFxfo.js} +1 -1
  75. package/lib/public/index.html +1 -1
  76. package/lib/schema.json +16 -12
  77. package/lib/src/InternalHttpClient.js +27 -5
  78. package/lib/src/XenonCapabilityManager.js +10 -3
  79. package/lib/src/app/dashboardPluginLink.js +117 -0
  80. package/lib/src/app/index.js +13 -34
  81. package/lib/src/app/openapi/control.yaml +6 -4
  82. package/lib/src/app/openapi/grid.yaml +8 -2
  83. package/lib/src/app/openapi/identity.yaml +103 -31
  84. package/lib/src/app/openapi/platform.yaml +33 -15
  85. package/lib/src/app/openapi/sessions.yaml +12 -3
  86. package/lib/src/app/routers/apikeys.js +14 -2
  87. package/lib/src/app/routers/auth.js +31 -6
  88. package/lib/src/app/routers/control.js +13 -5
  89. package/lib/src/app/routers/dashboard.js +42 -27
  90. package/lib/src/app/routers/grid.js +5 -3
  91. package/lib/src/app/routers/profile.js +21 -0
  92. package/lib/src/app/routers/users.js +12 -6
  93. package/lib/src/app/swagger.js +2 -0
  94. package/lib/src/app/ws/h264StreamWs.js +10 -1
  95. package/lib/src/app/ws/nodeSocketRelay.js +77 -11
  96. package/lib/src/config.js +1 -0
  97. package/lib/src/dashboard/commandLogFields.js +42 -0
  98. package/lib/src/dashboard/commands.js +5 -5
  99. package/lib/src/dashboard/event-manager.js +64 -204
  100. package/lib/src/dashboard/services/failure-analysis-service.js +118 -105
  101. package/lib/src/dashboard/services/failureCategories.js +264 -0
  102. package/lib/src/dashboard/sessionCommandSummary.js +39 -0
  103. package/lib/src/data-service/device-store.js +14 -1
  104. package/lib/src/data-service/prisma-store.js +19 -7
  105. package/lib/src/data-service/web-config-service.js +7 -0
  106. package/lib/src/device-managers/AndroidDeviceManager.js +61 -23
  107. package/lib/src/device-managers/IOSDeviceManager.js +10 -0
  108. package/lib/src/device-managers/android/AndroidH264StreamService.js +69 -20
  109. package/lib/src/device-managers/android/H264Multiplexer.js +38 -4
  110. package/lib/src/device-utils.js +29 -3
  111. package/lib/src/gateway/defaultGateway.js +1 -1
  112. package/lib/src/gateway/forwardToNode.js +6 -11
  113. package/lib/src/gateway/healReport.js +87 -0
  114. package/lib/src/gateway/hubSessionToken.js +27 -4
  115. package/lib/src/gateway/nodeWebDriverUrl.js +3 -5
  116. package/lib/src/gateway/sessionGateway.js +12 -2
  117. package/lib/src/generated/client/edge.js +4 -3
  118. package/lib/src/generated/client/index-browser.js +1 -0
  119. package/lib/src/generated/client/index.d.ts +32 -0
  120. package/lib/src/generated/client/index.js +4 -3
  121. package/lib/src/generated/client/package.json +1 -1
  122. package/lib/src/generated/client/schema.prisma +3 -0
  123. package/lib/src/generated/client/wasm.js +1 -0
  124. package/lib/src/helpers/outboundProxy.js +219 -0
  125. package/lib/src/index.js +21 -0
  126. package/lib/src/interceptors/CommandInterceptor.js +256 -196
  127. package/lib/src/interceptors/xenonScripts.js +28 -7
  128. package/lib/src/logger.js +3 -1
  129. package/lib/src/middleware/authMiddleware.js +15 -3
  130. package/lib/src/middleware/commandCaller.js +3 -3
  131. package/lib/src/middleware/verifyCredential.js +58 -1
  132. package/lib/src/plugin.js +16 -6
  133. package/lib/src/scripts/database-check.js +3 -3
  134. package/lib/src/scripts/initialize-database.js +35 -33
  135. package/lib/src/scripts/run-migrations.js +1079 -27
  136. package/lib/src/services/AICommandService.js +9 -2
  137. package/lib/src/services/AIService.js +192 -42
  138. package/lib/src/services/ApiKeyService.js +16 -5
  139. package/lib/src/services/EmailService.js +29 -0
  140. package/lib/src/services/InterceptorService.js +6 -2
  141. package/lib/src/services/OrphanSweeper.js +8 -0
  142. package/lib/src/services/SelectorStateService.js +11 -7
  143. package/lib/src/services/SelectorVerificationJob.js +21 -6
  144. package/lib/src/services/ServerManager.js +11 -1
  145. package/lib/src/services/SessionLifecycleService.js +118 -44
  146. package/lib/src/services/SocketClient.js +11 -0
  147. package/lib/src/services/SocketServer.js +380 -45
  148. package/lib/src/services/TeamService.js +5 -1
  149. package/lib/src/services/TracingService.js +171 -60
  150. package/lib/src/services/UserService.js +14 -3
  151. package/lib/src/services/UserSessionService.js +16 -4
  152. package/lib/src/services/bug-report/video-slice.js +4 -1
  153. package/lib/src/services/device-access/leaseOverride.js +7 -5
  154. package/lib/src/services/healing/FuzzyXmlHealingProvider.js +51 -0
  155. package/lib/src/services/healing/HealEtalonService.js +3 -2
  156. package/lib/src/services/healing/HealingOrchestrator.js +57 -72
  157. package/lib/src/services/healing/OcrHealingProvider.js +41 -64
  158. package/lib/src/services/healing/ResilioTreeHealingProvider.js +41 -50
  159. package/lib/src/services/healing/VisualAiHealingProvider.js +1 -1
  160. package/lib/src/services/healing/fingerprintIdentity.js +126 -0
  161. package/lib/src/services/healing/resilioPath.js +274 -0
  162. package/lib/src/services/identity/identityChanges.js +41 -0
  163. package/lib/src/services/logcat/SessionDeviceLogs.js +358 -0
  164. package/lib/src/services/logcat/deviceLogBook.js +164 -0
  165. package/lib/src/services/logcat/iosDriverLog.js +178 -0
  166. package/lib/src/services/ocr/ocrData.js +118 -0
  167. package/lib/src/services/ocr/vendor/LICENSE-tessdata.txt +202 -0
  168. package/lib/src/services/ocr/vendor/eng.traineddata.gz +0 -0
  169. package/lib/src/services/omni-vision/OmniVisionService.js +83 -56
  170. package/lib/src/services/passwordResetLink.js +50 -9
  171. package/lib/src/services/passwordResetMode.js +3 -1
  172. package/lib/src/services/publicUrl.js +45 -0
  173. package/lib/src/services/selector-health/SelectorVisibilityResolver.js +121 -0
  174. package/lib/src/services/session/sessionIdentity.js +5 -3
  175. package/lib/src/services/session/shutdownReason.js +26 -0
  176. package/lib/src/services/settings/aiEngineSettings.js +219 -0
  177. package/lib/src/services/token/JwtKeyService.js +8 -2
  178. package/lib/src/services/token/mcpTokenTtl.js +27 -0
  179. package/lib/src/services/token/mintedLifetime.js +51 -0
  180. package/lib/src/sessions/LocalSession.js +29 -1
  181. package/lib/src/sessions/RemoteSession.js +12 -2
  182. package/lib/src/sessions/SessionManager.js +4 -1
  183. package/lib/src/sessions/sessionMemory.js +25 -0
  184. package/lib/test/helpers/driver-log.js +38 -0
  185. package/lib/test/helpers/fake-ai-provider.js +188 -0
  186. package/lib/test/helpers/fake-http-proxy.js +106 -0
  187. package/lib/test/helpers/loki-stores.js +33 -0
  188. package/lib/test/helpers/otlp-probe.js +107 -0
  189. package/lib/test/helpers/page-sources.js +164 -0
  190. package/lib/test/helpers/scratch-database.js +57 -13
  191. package/lib/test/integration/androidDevices.spec.js +1 -1
  192. package/lib/test/integration/audit-ingest.spec.js +10 -10
  193. package/lib/test/integration/auth-flow.spec.js +9 -14
  194. package/lib/test/integration/auth-rate-limit.spec.js +6 -3
  195. package/lib/test/integration/bug-report-route.spec.js +22 -2
  196. package/lib/test/integration/forgot-password-rate-limit.spec.js +6 -3
  197. package/lib/test/integration/forgot-password.spec.js +17 -18
  198. package/lib/test/integration/ios/01iOSSimulator.spec.js +1 -1
  199. package/lib/test/integration/ios/02iOSDevices.spec.js +1 -1
  200. package/lib/test/integration/legacy-deprecation-headers.spec.js +5 -2
  201. package/lib/test/integration/migration.spec.js +6 -1
  202. package/lib/test/integration/node-pair-auth-rest.spec.js +5 -9
  203. package/lib/test/integration/ports-router.spec.js +4 -4
  204. package/lib/test/integration/prisma-device-store-add-devices.spec.js +2 -3
  205. package/lib/test/integration/prisma-device-store-team-filter.spec.js +2 -5
  206. package/lib/test/integration/profile-tokens.spec.js +10 -16
  207. package/lib/test/integration/recordings-router.spec.js +16 -16
  208. package/lib/test/integration/reset-revokes-sessions.spec.js +4 -9
  209. package/lib/test/integration/role-matrix.spec.js +4 -9
  210. package/lib/test/integration/sdk-leases-router.spec.js +9 -9
  211. package/lib/test/integration/sdk-version.spec.js +2 -2
  212. package/lib/test/integration/selector-health-endpoint.spec.js +5 -5
  213. package/lib/test/integration/selector-state-flow.spec.js +5 -5
  214. package/lib/test/integration/team-membership-migration.spec.js +73 -12
  215. package/lib/test/integration/team-visibility-apps.spec.js +15 -22
  216. package/lib/test/integration/team-visibility-control.spec.js +96 -69
  217. package/lib/test/integration/team-visibility-dashboard.spec.js +7 -23
  218. package/lib/test/integration/team-visibility-grid.spec.js +16 -15
  219. package/lib/test/integration/team-visibility-leases.spec.js +8 -11
  220. package/lib/test/integration/team-visibility-recordings.spec.js +6 -19
  221. package/lib/test/integration/team-visibility-sessions.spec.js +6 -19
  222. package/lib/test/integration/users-flow.spec.js +7 -12
  223. package/lib/test/integration/users-lockout.spec.js +5 -3
  224. package/lib/test/unit/EmailService.test.js +66 -0
  225. package/lib/test/unit/ResilioTreeHealingProvider.test.js +46 -19
  226. package/lib/test/unit/XenonCapabilityManager.spec.js +23 -0
  227. package/lib/test/unit/ai-call-time-limit.spec.js +130 -0
  228. package/lib/test/unit/ai-engine-settings.spec.js +338 -0
  229. package/lib/test/unit/ai-provider-switch.spec.js +130 -0
  230. package/lib/test/unit/ai-rate-limit.spec.js +126 -0
  231. package/lib/test/unit/android-adb-retry.spec.js +112 -0
  232. package/lib/test/unit/android-h264-viewers.spec.js +272 -0
  233. package/lib/test/unit/android-preview-hold.spec.js +3 -2
  234. package/lib/test/unit/apikeys-router.spec.js +84 -0
  235. package/lib/test/unit/authMiddleware.bearer.spec.js +9 -0
  236. package/lib/test/unit/authMiddleware.credentialLifetime.spec.js +149 -0
  237. package/lib/test/unit/bug-report/video-slice.spec.js +19 -0
  238. package/lib/test/unit/command-log-network-capture.spec.js +191 -0
  239. package/lib/test/unit/dashboard-events-device-logs.spec.js +255 -0
  240. package/lib/test/unit/dashboard-events-team-scope.spec.js +6 -3
  241. package/lib/test/unit/dashboard-plugin-link.spec.js +213 -0
  242. package/lib/test/unit/database-check.spec.js +1 -0
  243. package/lib/test/unit/device-log-book.spec.js +180 -0
  244. package/lib/test/unit/device-utils.spec.js +13 -4
  245. package/lib/test/unit/enable-dashboard-option.spec.js +57 -0
  246. package/lib/test/unit/event-log-session-data.spec.js +251 -0
  247. package/lib/test/unit/failure-analysis.spec.js +196 -0
  248. package/lib/test/unit/failure-categories.spec.js +130 -0
  249. package/lib/test/unit/failure-categorization.spec.js +393 -0
  250. package/lib/test/unit/fingerprint-identity.spec.js +433 -0
  251. package/lib/test/unit/h264-multiplexer.spec.js +46 -0
  252. package/lib/test/unit/heal-report.spec.js +71 -0
  253. package/lib/test/unit/healing-instrumentation.spec.js +6 -1
  254. package/lib/test/unit/healing-tier-gate.spec.js +74 -29
  255. package/lib/test/unit/healing-tiers-every-session.spec.js +219 -0
  256. package/lib/test/unit/hub-node-gateway-appium-server.spec.js +243 -1
  257. package/lib/test/unit/interceptor-visual-elements.spec.js +192 -0
  258. package/lib/test/unit/ios-driver-log.spec.js +168 -0
  259. package/lib/test/unit/ios-simulator-session-readiness.spec.js +187 -0
  260. package/lib/test/unit/ios-simulator-session-teardown.spec.js +158 -0
  261. package/lib/test/unit/lease/lease-override.spec.js +23 -6
  262. package/lib/test/unit/lease/session-lease-proof.spec.js +16 -4
  263. package/lib/test/unit/logcat-ws.spec.js +78 -37
  264. package/lib/test/unit/logger-json-levels.spec.js +44 -0
  265. package/lib/test/unit/mcp-token-ttl.spec.js +38 -0
  266. package/lib/test/unit/observability-example-loki.spec.js +25 -0
  267. package/lib/test/unit/ocr-healing-tier-real-ocr.spec.js +113 -0
  268. package/lib/test/unit/ocr-healing-tier.spec.js +122 -0
  269. package/lib/test/unit/ocr-offline.spec.js +213 -0
  270. package/lib/test/unit/omni-virtual-element-store.spec.js +301 -0
  271. package/lib/test/unit/omni-vision-ios-points.spec.js +0 -2
  272. package/lib/test/unit/omni-vision.spec.js +5 -7
  273. package/lib/test/unit/openapi-for-site.spec.js +80 -0
  274. package/lib/test/unit/outbound-proxy.spec.js +320 -0
  275. package/lib/test/unit/package-engines.spec.js +27 -0
  276. package/lib/test/unit/passwordResetMode.test.js +10 -2
  277. package/lib/test/unit/port-exhaustion.spec.js +2 -1
  278. package/lib/test/unit/profile-router.test.js +122 -1
  279. package/lib/test/unit/proxy-option.spec.js +358 -0
  280. package/lib/test/unit/queue-requester.spec.js +1 -1
  281. package/lib/test/unit/reset-link-address.spec.js +266 -0
  282. package/lib/test/unit/reset-link.test.js +10 -4
  283. package/lib/test/unit/resilio-path-healing.spec.js +270 -0
  284. package/lib/test/unit/run-migrations-database.spec.js +807 -0
  285. package/lib/test/unit/run-migrations-fail-fast.test.js +41 -27
  286. package/lib/test/unit/run-migrations.test.js +864 -0
  287. package/lib/test/unit/selector-health-actions.spec.js +3 -1
  288. package/lib/test/unit/selector-learning-every-session.spec.js +179 -0
  289. package/lib/test/unit/selector-state-service.spec.js +72 -23
  290. package/lib/test/unit/selector-verification-clean-build.spec.js +130 -0
  291. package/lib/test/unit/selector-verification-job.spec.js +28 -19
  292. package/lib/test/unit/selector-verification-missed-regression.spec.js +2 -2
  293. package/lib/test/unit/selector-visibility-resolver.spec.js +209 -0
  294. package/lib/test/unit/self-healing-boot.spec.js +10 -5
  295. package/lib/test/unit/self-healing-setting.spec.js +7 -6
  296. package/lib/test/unit/session-app-resolution.spec.js +5 -1
  297. package/lib/test/unit/session-attribution-wiring.spec.js +41 -13
  298. package/lib/test/unit/session-create-credential-owner.spec.js +242 -0
  299. package/lib/test/unit/session-credential-strip.spec.js +1 -1
  300. package/lib/test/unit/session-device-logs-ios.spec.js +180 -0
  301. package/lib/test/unit/session-device-logs.spec.js +356 -0
  302. package/lib/test/unit/session-end-failure-analysis.spec.js +133 -0
  303. package/lib/test/unit/session-log-indexes.spec.js +64 -3
  304. package/lib/test/unit/socket-team-scope.integration.spec.js +749 -0
  305. package/lib/test/unit/socketServer.scopedEmit.spec.js +237 -5
  306. package/lib/test/unit/socketServer.sessionCookie.spec.js +2 -1
  307. package/lib/test/unit/stream-start-pipelines.spec.js +72 -18
  308. package/lib/test/unit/token-mint-limits.spec.js +165 -0
  309. package/lib/test/unit/tracing-export-routing.spec.js +137 -0
  310. package/lib/test/unit/tracing-session-spans.spec.js +337 -0
  311. package/lib/test/unit/unexpected-shutdown-reason.spec.js +163 -0
  312. package/lib/test/unit/verify-credential.spec.js +33 -0
  313. package/lib/test/unit/vision-assertion.spec.js +3 -2
  314. package/lib/test/unit/web-config-service.spec.js +19 -0
  315. package/lib/tsconfig.tsbuildinfo +1 -1
  316. package/package.json +6 -5
  317. package/prisma/migrations/20261004174413_locator_etalon_path/migration.sql +2 -0
  318. package/prisma/schema.prisma +3 -0
  319. package/schema.json +16 -12
  320. package/scripts/dev/readme-screenshots.js +276 -23
  321. package/scripts/dev/screenshot-fixtures/logcat.js +157 -0
  322. package/scripts/dev/screenshot-fixtures/phone-screen.html +469 -0
  323. package/scripts/dev/screenshot-fixtures/session.js +242 -0
  324. package/scripts/export-openapi.js +32 -0
  325. package/scripts/lib/openapi-for-site.js +79 -0
  326. package/lib/public/assets/BugReportButton-BAt0_pzq.js +0 -15
  327. package/lib/public/assets/DeviceMosaicView-BYaQHhTf.js +0 -2
  328. package/lib/public/assets/ai-settings-CsuJroRf.js +0 -21
  329. package/lib/public/assets/device-explorer-CdO6_nrn.js +0 -282
  330. package/lib/public/assets/forgot-password-CGnkRgE9.js +0 -1
  331. package/lib/public/assets/index-BbKEXUFH.js +0 -219
  332. package/lib/public/assets/runbook-page-CMMeQml9.js +0 -124
  333. package/lib/public/assets/session-detail-page-COL_RZxw.js +0 -4
  334. package/lib/src/scripts/prepare-prisma.js +0 -89
  335. /package/lib/public/assets/{BugReportButton-CPBjfiv4.css → index-CPBjfiv4.css} +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "prisma-client-ec1ae6fb328d1bc102086acd1f77e77477081d17b653d7f5092f083d0c8a4d34",
2
+ "name": "prisma-client-51d1df0b46f05c51a020cdf82ebc5860c67366c00fe846037d4445f0f8195b4a",
3
3
  "main": "index.js",
4
4
  "types": "index.d.ts",
5
5
  "browser": "index-browser.js",
@@ -307,6 +307,9 @@ model LocatorEtalon {
307
307
  strategy String
308
308
  attributes String
309
309
  nodeName String
310
+ /// The element's path through the page source when the selector last
311
+ /// worked (JSON, resilioPath.ts), for the Resilio healing tier.
312
+ path String?
310
313
  lastSeen DateTime @default(now())
311
314
  createdAt DateTime @default(now())
312
315
  updatedAt DateTime @updatedAt
@@ -353,6 +353,7 @@ exports.Prisma.LocatorEtalonScalarFieldEnum = {
353
353
  strategy: 'strategy',
354
354
  attributes: 'attributes',
355
355
  nodeName: 'nodeName',
356
+ path: 'path',
356
357
  lastSeen: 'lastSeen',
357
358
  createdAt: 'createdAt',
358
359
  updatedAt: 'updatedAt'
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.outboundProxyFor = outboundProxyFor;
16
+ exports.envProxyFor = envProxyFor;
17
+ exports.proxyAgentFor = proxyAgentFor;
18
+ exports.socketProxyAgentFor = socketProxyAgentFor;
19
+ exports.axiosProxyConfig = axiosProxyConfig;
20
+ const typedi_1 = require("typedi");
21
+ const http_proxy_agent_1 = require("http-proxy-agent");
22
+ const https_proxy_agent_1 = require("https-proxy-agent");
23
+ const logger_1 = __importDefault(require("../logger"));
24
+ const PluginContext_1 = require("../PluginContext");
25
+ /**
26
+ * The proxy for one of Xenon's own calls to another server (a hub's to its
27
+ * nodes and to a cloud provider, a node's to its hub, and the rest of
28
+ * Xenon's internal calls), one rule whichever client makes the call:
29
+ *
30
+ * 1. None for a host `no_proxy` / `NO_PROXY` names (envProxyFor's list).
31
+ * 2. The `proxy` plugin option when it is set, for http and https alike,
32
+ * except for a loopback host (`localhost`, 127.x, ::1): a proxy elsewhere
33
+ * can't reach this machine's loopback.
34
+ * 3. Else the environment's proxy for the URL's scheme (envProxyFor).
35
+ *
36
+ * Through 2.15 the option reached one call, the create a hub sends to a node
37
+ * or a cloud provider; that session's commands, screenshots and heartbeats,
38
+ * device control, the sockets and a node's calls to its hub took the
39
+ * environment's proxy instead, or none.
40
+ */
41
+ function outboundProxyFor(target, opts = {}) {
42
+ var _a, _b;
43
+ const url = toUrl(target);
44
+ const scheme = schemeOf(url);
45
+ if (!scheme)
46
+ return undefined;
47
+ const env = (_a = opts.env) !== null && _a !== void 0 ? _a : process.env;
48
+ if (namedByNoProxy(url, env))
49
+ return undefined;
50
+ const option = 'option' in opts ? opts.option : pluginProxyOption();
51
+ const configured = proxyOptionUrl(option, (_b = opts.warn) !== null && _b !== void 0 ? _b : warnOnce);
52
+ if (configured && !isLoopback(url.hostname))
53
+ return configured;
54
+ return schemeProxy(scheme, env);
55
+ }
56
+ /**
57
+ * The environment's proxy for a URL, by the rule axios (0.27's http adapter)
58
+ * applies to Xenon's axios calls:
59
+ * - `http_proxy` or `HTTP_PROXY` for an http URL, `https_proxy` or
60
+ * `HTTPS_PROXY` for an https one, the lower-case name first (ws and wss
61
+ * count as http and https);
62
+ * - none when `no_proxy` or `NO_PROXY` (the lower-case name first; a
63
+ * comma-separated list) has `*`, the URL's host name, or a suffix of it
64
+ * starting with a dot (`.lab.example`). An entry is a host name only: one
65
+ * with a port matches nothing, as in axios.
66
+ *
67
+ * Through 2.15 a command forwarded to a node took HTTP_PROXY or HTTPS_PROXY
68
+ * whatever its scheme and ignored NO_PROXY, the live-preview and logcat
69
+ * sockets ignored every proxy, and so did a node fetching its hub's keys.
70
+ */
71
+ function envProxyFor(target, env = process.env) {
72
+ const url = toUrl(target);
73
+ const scheme = schemeOf(url);
74
+ if (!scheme || namedByNoProxy(url, env))
75
+ return undefined;
76
+ return schemeProxy(scheme, env);
77
+ }
78
+ /**
79
+ * An agent sending an HTTP request for `target` through its proxy, or
80
+ * undefined to go straight there: the request in absolute form to the proxy
81
+ * for an http URL, a CONNECT tunnel for an https one.
82
+ */
83
+ function proxyAgentFor(target, tls = {}) {
84
+ const proxy = outboundProxyFor(target);
85
+ if (!proxy)
86
+ return undefined;
87
+ const url = toUrl(target);
88
+ return url.protocol === 'https:' ? new TunnelAgent(proxy, tls) : new http_proxy_agent_1.HttpProxyAgent(proxy);
89
+ }
90
+ /**
91
+ * An agent opening a WebSocket for `target` (ws or wss) through its proxy, or
92
+ * undefined to go straight there. Always a CONNECT tunnel: an upgrade sent to
93
+ * a proxy in absolute form is not reliably passed on.
94
+ */
95
+ function socketProxyAgentFor(target, tls = {}) {
96
+ const proxy = outboundProxyFor(target);
97
+ return proxy ? new TunnelAgent(proxy, tls) : undefined;
98
+ }
99
+ /**
100
+ * An axios request's proxy settings for `target`: through its proxy's agent,
101
+ * or none. Either way `proxy: false`, since the decision is made here, by
102
+ * outboundProxyFor; axios's own lookup reads the environment only. With no
103
+ * proxy, the caller's own agents stay.
104
+ */
105
+ function axiosProxyConfig(target, tls = {}) {
106
+ const agent = proxyAgentFor(target, tls);
107
+ return agent ? { proxy: false, httpAgent: agent, httpsAgent: agent } : { proxy: false };
108
+ }
109
+ /**
110
+ * A CONNECT tunnel that checks the server behind it as the caller asked.
111
+ * HttpsProxyAgent's own options are for the connection to the proxy; the
112
+ * tunnelled TLS takes the request's, which axios doesn't fill in. So through
113
+ * 2.15 `tlsRejectUnauthorized` never reached a node or cloud provider that a
114
+ * proxy stood in front of.
115
+ */
116
+ class TunnelAgent extends https_proxy_agent_1.HttpsProxyAgent {
117
+ constructor(proxy, targetTls) {
118
+ super(proxy);
119
+ this.targetTls = targetTls;
120
+ }
121
+ connect(req, opts) {
122
+ const _super = Object.create(null, {
123
+ connect: { get: () => super.connect }
124
+ });
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ const tls = this.targetTls.rejectUnauthorized === undefined
127
+ ? {}
128
+ : { rejectUnauthorized: this.targetTls.rejectUnauthorized };
129
+ return _super.connect.call(this, req, Object.assign(Object.assign({}, opts), tls));
130
+ });
131
+ }
132
+ }
133
+ /**
134
+ * The `proxy` option as a proxy URL: a string as it is (http:// added when
135
+ * it names no scheme), or `{ protocol, host, port, auth: { username,
136
+ * password } }` (protocol http by default, credentials escaped). One that
137
+ * names no host is no proxy, said once.
138
+ */
139
+ function proxyOptionUrl(option, warn) {
140
+ var _a, _b;
141
+ if (option === undefined || option === null || option === '')
142
+ return undefined;
143
+ if (typeof option === 'string') {
144
+ const text = option.trim();
145
+ if (text === '')
146
+ return undefined;
147
+ return hasScheme(text) ? text : `http://${text}`;
148
+ }
149
+ const value = option;
150
+ if (typeof option !== 'object' || typeof value.host !== 'string' || value.host.trim() === '') {
151
+ warn(`The proxy option ${JSON.stringify(option)} names no host, so it is not used: ` +
152
+ "Xenon's calls to other servers take the environment's proxy, if any.");
153
+ return undefined;
154
+ }
155
+ const protocol = typeof value.protocol === 'string' && value.protocol !== ''
156
+ ? value.protocol.replace(/:$/, '')
157
+ : 'http';
158
+ const port = value.port === undefined || value.port === null ? '' : `:${value.port}`;
159
+ const username = (_a = value.auth) === null || _a === void 0 ? void 0 : _a.username;
160
+ const password = (_b = value.auth) === null || _b === void 0 ? void 0 : _b.password;
161
+ const credentials = typeof username === 'string' && username !== ''
162
+ ? `${encodeURIComponent(username)}${typeof password === 'string' ? `:${encodeURIComponent(password)}` : ''}@`
163
+ : '';
164
+ return `${protocol}://${credentials}${value.host.trim()}${port}`;
165
+ }
166
+ const warned = new Set();
167
+ function warnOnce(message) {
168
+ if (warned.has(message))
169
+ return;
170
+ warned.add(message);
171
+ logger_1.default.warn(message);
172
+ }
173
+ function pluginProxyOption() {
174
+ var _a;
175
+ try {
176
+ return (_a = typedi_1.Container.get(PluginContext_1.PluginContext).pluginArgs) === null || _a === void 0 ? void 0 : _a.proxy;
177
+ }
178
+ catch (_b) {
179
+ return undefined;
180
+ }
181
+ }
182
+ function toUrl(target) {
183
+ return typeof target === 'string' ? new URL(target) : target;
184
+ }
185
+ function schemeOf(url) {
186
+ const scheme = url.protocol.replace(/:$/, '').replace(/^ws(s?)$/, 'http$1');
187
+ return scheme === 'http' || scheme === 'https' ? scheme : undefined;
188
+ }
189
+ function hostOf(url) {
190
+ return url.hostname.replace(/^\[(.*)\]$/, '$1');
191
+ }
192
+ function namedByNoProxy(url, env) {
193
+ const noProxy = env.no_proxy || env.NO_PROXY;
194
+ if (!noProxy)
195
+ return false;
196
+ const host = hostOf(url);
197
+ return noProxy
198
+ .split(',')
199
+ .map((entry) => entry.trim())
200
+ .some((entry) => entry !== '' &&
201
+ (entry === '*' || entry === host || (entry.startsWith('.') && host.endsWith(entry))));
202
+ }
203
+ function schemeProxy(scheme, env) {
204
+ const proxy = env[`${scheme}_proxy`] || env[`${scheme.toUpperCase()}_PROXY`];
205
+ if (!proxy)
206
+ return undefined;
207
+ return hasScheme(proxy) ? proxy : `http://${proxy}`;
208
+ }
209
+ function hasScheme(text) {
210
+ return /^[a-z][a-z0-9+.-]*:\/\//i.test(text);
211
+ }
212
+ function isLoopback(hostname) {
213
+ const host = hostname.replace(/^\[(.*)\]$/, '$1').toLowerCase();
214
+ return (host === 'localhost' ||
215
+ host.endsWith('.localhost') ||
216
+ /^127(\.\d{1,3}){3}$/.test(host) ||
217
+ host === '::1' ||
218
+ host === '0:0:0:0:0:0:0:1');
219
+ }
package/lib/src/index.js CHANGED
@@ -68,6 +68,12 @@ const cleanup = () => __awaiter(void 0, void 0, void 0, function* () {
68
68
  // Bounded so a hung driver can't hold up systemd (default 90s timeout).
69
69
  const { ShutdownCoordinator } = yield Promise.resolve().then(() => __importStar(require('./services/ShutdownCoordinator')));
70
70
  yield typedi_1.Container.get(ShutdownCoordinator).drain(15000);
71
+ // Telemetry next, as early as it can be: on SIGTERM Appium exits before
72
+ // Phase 2 (see the 'exit' hook below), and placed last it never ran. What
73
+ // the OTel exporters still hold is sent, and the spans of sessions still
74
+ // running on a node or at a cloud provider end, saying so. Lines logged
75
+ // after this aren't exported.
76
+ yield shutDownTelemetry(3000);
71
77
  const { default: IOSStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/ios/IOSStreamService')));
72
78
  const { default: AndroidStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/android/AndroidStreamService')));
73
79
  const { LogcatStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/android/LogcatStreamService')));
@@ -94,11 +100,26 @@ const cleanup = () => __awaiter(void 0, void 0, void 0, function* () {
94
100
  logger_1.default.error(`❌ [Xenon] Cleanup failed: ${err.message}`);
95
101
  }
96
102
  finally {
103
+ // When the drain threw, the telemetry wasn't shut down above. A second
104
+ // call does nothing.
105
+ yield shutDownTelemetry(1000);
97
106
  // Principal Delay: Wait 2 seconds before hard-exiting to allow
98
107
  // other async handlers (like hub unregistration) to finish.
99
108
  setTimeout(() => process.exit(0), 2000);
100
109
  }
101
110
  });
111
+ function shutDownTelemetry(budgetMs) {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ var _a;
114
+ try {
115
+ const { TracingService } = yield Promise.resolve().then(() => __importStar(require('./services/TracingService')));
116
+ yield typedi_1.Container.get(TracingService).shutdownWithin(budgetMs);
117
+ }
118
+ catch (err) {
119
+ logger_1.default.warn(`[Xenon] Telemetry shutdown failed: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
120
+ }
121
+ });
122
+ }
102
123
  process.on('SIGINT', cleanup);
103
124
  process.on('SIGTERM', cleanup);
104
125
  // Last-resort synchronous net for every long-lived sidecar.